【发布时间】:2012-08-11 03:49:05
【问题描述】:
CompilationRepresentationFlags.UseNullAsTrueValue可以用来
允许在可区分联合中使用 null 作为 null 鉴别器的表示
Option.None 是这方面最突出的例子。
为什么这很有用?与传统的联合案例检查机制(生成的Tag 属性)相比,空值检查有何优势?
这可能会导致意想不到的行为:
Some(1).ToString() //"Some(1)"
None.ToString() //NullReferenceException
编辑
我测试了 Jack 的断言,即与 null 而不是静态只读字段相比更快。
[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
type T<'T> =
| Z
| X of 'T
let t = Z
使用 ILSpy,我可以看到 t 编译为 null(如预期的那样):
public static Test.T<a> t<a>()
{
return null;
}
测试:
let mutable i = 0
for _ in 1 .. 10000000 do
match t with
| Z -> i <- i + 1
| _ -> ()
结果:
真实:00:00:00.036,CPU:00:00:00.046,GC gen0:0,gen1:0,gen2:0
如果CompilationRepresentation 属性被移除,t 将成为静态只读字段:
public static Test.T<a> t<a>()
{
return Test.T<a>.Z;
}
public static Test.T<T> Z
{
[CompilationMapping(SourceConstructFlags.UnionCase, 0)]
get
{
return Test.T<T>._unique_Z;
}
}
internal static readonly Test.T<T> _unique_Z = new Test.T<T>._Z();
而且结果是一样的:
真实:00:00:00.036,CPU:00:00:00.031,GC gen0:0,gen1:0,gen2:0
模式匹配在前一种情况下编译为t == null,在后一种情况下编译为t is Z。
【问题讨论】: