Por que nenhum é representado como nulo?

CompilationRepresentationFlags.UseNullAsTrueValue pode ser usado para

Permitir o uso de null como uma representação para discriminadores nulos em uma união discriminada

Option.None é o exemplo mais proeminente disso.

Por que isso é útil? Como é uma verificação nula melhor do que o mecanismo tradicional para verificar casos de união (o geradoTag propriedade)?

Isso leva a um comportamento talvez inesperado:

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

Eu testei a afirmação de Jack de que comparar com null em vez de um campo readonly estático é mais rápido.

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

let t = Z

Usando ILSpy, eu posso vert compila para null (como esperado):

public static Test.T<a> t<a>()
{
    return null;
}

O teste:

let mutable i = 0
for _ in 1 .. 10000000 do
  match t with
  | Z -> i <- i + 1
  | _ -> ()

Os resultados:

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

Se oCompilationRepresentation o atributo é removidot torna-se um campo de somente leitura estática:

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

E os resultados são os mesmos:

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

A correspondência de padrões é compilada comot == null no primeiro caso et is Z no ultimo.

questionAnswers(2)

yourAnswerToTheQuestion