2017-02-01 1 views
10

F#オプションタイプのいくつかのプロパティは、C#プロジェクトからは見えません。タイプを調べることによって、私は多かれ少なかれ理由を見ることができますが、正確に何が起こっているのか、なぜこれらの選択がなされたのか、問題を回避する最良の方法を本当に理解していません。FSharpOptionの一部のプロパティ(IsSomeやIsNoneなど)がC#から見えないのはなぜですか?

問題を示す抜粋です。私は2つのプロジェクト、C#プロジェクトとF#プロジェクトを含むVS2015ソリューションを持っています。

type Foo() = 

    member this.Bar() = Some(1) 

さらに、F#で、私はこのような何か書くことができます::だから、オプションタイプが名前付きプロパティを持っているように思われる

let option = (new Foo()).Bar() 
let result = if option.IsNone then "Is none" else "Is some" 

をF#プロジェクトでは、私は次のように定義されたクラスを持っていますIsNone。さて、C#プロジェクトでは、F#プロジェクトからコンパイルされた.dllへの参照があります。これにより私は例えば

var optionType = new Foo().Bar(); 

変数optionTypeFSharpOption<int>です。上記のように、F#プロジェクトでオプションタイプを使用すると、通常、たとえばIsSomeIsNoneのプロパティにアクセスできます。しかし、optionType.IsNoneのようなものを書き込もうとすると、「プロパティ、インデクサーまたはイベント...が言語でサポートされていません」というCS1546エラーが表示されます。これに一致して、IntelliSenseがプロパティを検出しません:

Intellisense does not detect the IsSome and IsNone properties

FSharpOptionタイプを検査する際に今、私はIsNoneとIsSome「プロパティ」は、静的メソッド表示されていることがわかります。

FSharpOption class signature from C#を一方

Iは、F#1からタイプを検査する場合、私の代わりに、以下参照:

FSharpOption class signature from F#

ここでは、プロパティIsSomeIsNoneの「存在」が明白です。 VS2015は、これらのプロパティ上にカーソルを置くと、次のような注釈が表示されます。「包含するタイプでは、ヌル・ユニオンの大文字小文字の表現値として 'null'を使用できます。このメンバーは静的メンバーとしてコンパイルされます。これは、静的メソッド(lukegvとFyodor Soikinに記載されているように)以外のプロパティが利用できない理由です。

したがって、状況は次のようになります。コンパイルされたFSharpOption型には、IsNoneおよびIsSomeプロパティがありません。これらのプロパティをエミュレートする機能を有効にするために、F#のシーンの背後に何かが起こっています。

私はMicrosoft.FSharp.CoreのOptionModuleを使用してこの問題を回避できることを知っています。しかし、この機能は、F#コアライブラリの設計者が意識して選択したようです。選択の理由は何ですか? OptionModuleを適切な方法で使用しているか、C#のFSharpOption<T>タイプを使用するより良い方法がありますか?

答えて

10

これは、optionのコンパイル方法と関係があります。 Someの値は、クラスのインスタンスを作成し、クラスの値をラップすることで直接コンパイルされます。しかし、Noneの値は実際には値ではなく、ちょうどnullです。

これを試してみてください:

let a: int option = Some 1 
let b: int option = None 
let a_isNull = obj.ReferenceEquals(a, null) // a_isNull = false 
let b_isNull = obj.ReferenceEquals(b, null) // b_isNull = true 

これは、実行時にサイクルの節約の最適化である(これもNonewill show up as null in the debugger's Watch windowという理由です)。 CompilationRepresentationFlags.UseNullAsTrueValueを適用することによって自分のユニオンタイプにも使用できます)

このタイプの値はnullなので、これらの値に対して実際にプロパティやメソッドを使用することはできません。値がnullの場合、クラッシュするだけです。そのため、すべての操作に常にOptionModuleを使用する必要があります。

なぜこれらのプロパティはインテリセンスに表示されないのですか?それは、それらがstaticであるからです。なぜ彼らがそこに存在しているのか分かりませんが。おそらくコンパイラのアーティファクト。

+3

ありがとうございます。なぜなら、None値が本当にnullであるという事実は、IsNoneとIsSomeのプロパティが削除された理由の良い説明です。私は、コンパイルされたクラスでは、 "プロパティ"は静的であることをあなたとlukegvの発言を含めるために少し質問を編集しました。 –

+0

Sooo ...まだメカニックと理由がないのですか?それ以外は不明ですか? –

+0

いいえ、意味があります、ありがとう:-) –

2

私はよくF#の精通ではないのですが、それはすべてのCLRであることから、私の答えは、ビューのC#の観点からである:生成されたクラス定義で

、両方IsNoneIsSomeは静的であり、そのためにはできませんoptionType(IntelliSense経由でもコード内でもない)経由でアクセスできます。プロパティValueは静的ではなく、アクセスすることができます。

関連する問題