为什么"printf "%A" None"输出为空



为什么printfSome 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