为什么printf
为Some x
输出Some x
,而为None
输出<null>
?
> printfn "%A" (Some 123);;
Some 123
val it : unit = ()
> printfn "%A" None;;
<null>
val it : unit = ()
在编译的代码中,F#使用null
值来表示option<'T>
的None
情况,以提高效率。通过使用CompilationRepresentationFlags.
UseNullAsTrueValue
编译标志(请参阅MSDN文档(,您实际上可以将其用于您自己的有区别的联合。
您可以通过使用Object.ReferenceEquals
方法看到:
> let n = None;;
val n : 'a option
> System.Object.ReferenceEquals(n, null);;
val it : bool = true
为什么printfn "%A"
只打印内部表示,而没有意识到这实际上代表了None
的情况?
我认为答案是,打印是使用反射动态完成的,因此在某个时刻,参数只是转换为obj
类型的值。一旦您有一个obj
类型的值null
,就不可能恢复它在强制转换之前的类型,因此您无法发现null
实际上代表None
(因为null.GetType()
失败(。据推测,打印可以使用静态类型信息以这种方式获取类型信息,但这可能更难实现。
这实际上是一种不会消失的旧行为。Tomas的答案对于较旧的FSI是正确的,但如果你安装了较新的东西(如.NET Core 3.1最新版本或.NET 5预览版(,你会在dotnet fsi
中看到None
在你的示例中格式化为None
。