Почему None представлен как ноль?

CompilationRepresentationFlags.UseNullAsTrueValue может быть использован для

Permit the use of null as a representation for nullary discriminators in a discriminated union

Option.None самый яркий пример этого.

Почему это полезно? Как нулевая проверка лучше, чем традиционный механизм проверки объединений (сгенерированныйTag имущество)?

Это может привести к неожиданному поведению:

Some(1).ToString() //"Some(1)"
None.ToString()    //NullReferenceException
EDIT

Я проверил утверждение Джека о том, что сравнение со значением NULL вместо статического поля только для чтения выполняется быстрее.

[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
type T<'T> =
  | Z
  | X of 'T

let t = Z

Используя ILSpy, я вижуt компилируется в ноль (как и ожидалось):

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
  | _ -> ()

Результаты, достижения:

Real: 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();

И результаты одинаковы:

Real: 00:00:00.036, CPU: 00:00:00.031, GC gen0: 0, gen1: 0, gen2: 0

Сопоставление с образцом составляется какt == null в первом случае иt is Z в последнем.

Ответы на вопрос(2)

Ваш ответ на вопрос