Ale*_*kol 11 c# f# interop properties
在我看来,F#选项类型的某些属性在C#项目中是不可见的.通过检查类型,我可以看到或多或少的原因,但我真的不明白究竟发生了什么,为什么做出这些选择或如何最好地规避问题.
这里有一些片段展示了这个问题.我有一个包含两个项目的VS2015解决方案,一个C#项目和一个F#项目.在F#项目中,我有一个类定义如下:
type Foo () =
member this.Bar () = Some(1)
Run Code Online (Sandbox Code Playgroud)
此外,在F#中,我可以这样写:
let option = (new Foo()).Bar()
let result = if option.IsNone then "Is none" else "Is some"
Run Code Online (Sandbox Code Playgroud)
所以看起来选项类型有一个名为的属性IsNone.现在,在C#项目中,我引用了从F#项目编译的.dll.这允许我写例如
var optionType = new Foo().Bar();
Run Code Online (Sandbox Code Playgroud)
变量optionType是一个FSharpOption<int>.如上所述,当我在F#项目中使用选项类型时,我通常可以访问例如IsSome和IsNone属性.但是,当我尝试写类似的东西时optionType.IsNone,我得到CS1546错误"属性,索引器或事件......语言不支持".与此一致,Intellisense没有检测到属性:
现在,在检查FSharpOption类型时,我可以看到IsNone和IsSome"属性"显示为静态方法:
另一方面,当我从F#检查类型时,我看到以下内容:
在这里,属性的"存在" IsSome,并IsNone可见一斑.将光标悬停在这些属性上,VS2015给出了以下注释:"包含类型可以使用'null'作为其nullary union case的表示值.该成员将被编译为静态成员." 这就是除了静态方法(如lukegv和Fyodor Soikin所述)之外,这些属性不可用的原因.
因此,情况似乎如下:编译的FSharpOption类型没有任何IsNone和IsSome属性.F#中的幕后工作正在进行,以启用模拟这些属性的功能.
我知道我可以通过使用OptionModuleMicrosoft.FSharp.Core 来解决这个问题.但是,似乎这个功能是F#核心库的架构师有意识的选择.选择的原因是什么?并且正在使用OptionModule正确的解决方案,还是有更好的方法来使用FSharpOption<T>C#中的类型?
Fyo*_*kin 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
Run Code Online (Sandbox Code Playgroud)
(这也是None值将显示null在调试器的Watch窗口中的原因)
这是一种在运行时节省大量周期的优化.(你也可以通过申请将它用于你自己的工会类型CompilationRepresentationFlags.UseNullAsTrueValue)
现在,由于此类型的某些值可能存在null,因此您无法在这些值上使用属性或方法.如果值恰好是null,你就会崩溃.这就是为什么你应该总是使用OptionModulefor all操作.
至于为什么这些属性没有出现在intellisense中 - 那是因为它们是static.虽然我不确定他们为什么会在那里出现.也许是编译器工件.