ToString anulável ()

142

Vejo em todos os lugares construções como:

int? myVar = null;
string test = myVar.HasValue ? myVar.Value.ToString() : string.Empty;

Por que não usar simplesmente:

string test = myVar.ToString();

Isso não é exatamente o mesmo? Pelo menos Reflector diz que:

public override string ToString()
{
  if (!this.HasValue)
  {
    return "";
  }
  return this.value.ToString();
}

Então, isso está correto (a versão mais curta) ou estou faltando alguma coisa?

IamDeveloper
fonte
1
Eu não vi um código como este :)
tymtam

Respostas:

112

Você está bem correto. Também nesta pergunta , a solução anterior é sugerida enquanto ninguém percebe que ToString()já dá a resposta correta.

Talvez o argumento para uma solução mais detalhada seja a legibilidade: quando você invoca ToString()algo que deveria ser null, geralmente espera um NullReferenceException, embora aqui não seja lançado.

Tomas Vana
fonte
21
Na verdade, pelo menos duas pessoas notaram: Eric Lippert e Johannes Rössel.
Jon Skeet
7
Embora tenha certeza de que não foi isso que você quis dizer, a referência não é realmente nula aqui. Anulável <T> é um tipo de valor. É por isso que chamar ToString()funciona sem NullReferenceExceptionser lançado.
Thorarin
2
Se essa fosse a mentalidade, você esperaria .HasValueainda lançar essa exceção.
Extragorey
Outro motivo pelo qual as pessoas usam a versão detalhada pode ser a paridade com expressões como myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullonde você precisa do objeto desembrulhado para acessar o ToStringmétodo desejado . Claro, há uma solução mais concisa para isso também:$"{myNullableDateTime:d}"
Extragorey
14

Eu acho que muitas pessoas têm tais verificações, porque não é um comportamento natural de um objeto que pode conter valor nulo.

Andrew Bezzub
fonte
@ Andrew, concordou, porque as pessoas (como eu) pensam a princípio que isso causará uma exceção.
precisa
1
Eu não tinha ideia de que era esse o comportamento. Definitivamente, eu pensaria que qualquer construção que retorne true para (x == null) também lançaria uma NullReferenceException se você chamar x.ToString ().
Dan Bryant
5

Não, você está correto, a versão mais curta é a mesma que outras pessoas fizeram a esse respeito. A outra construção que costumo usar muito, em vez do ternário com valores nulos, é o operador coalescente nulo. que também protege você de nulos. Para ToString () não é necessário (como você apontou), mas para valores int padrão (por exemplo) funciona bem, por exemplo:

int page = currentPage ?? 1;

que permite executar todas as operações inteiras na página sem a primeira verificação explícita nula e a chamada do valor em currentPage (onde currentPage é um int? talvez passado como um parâmetro)

Paulo
fonte
5

Eu sei, muito depois que foi relevante, mas ... suspeito que seja porque para tipos anuláveis ​​como int? o método .ToString () não permite que você use seqüências de caracteres de formato. Consulte Como posso formatar um DateTime anulável com ToString ()? . Talvez no código original houvesse uma string de formato em .ToString () ou talvez o codificador tivesse esquecido que .ToString () sem a string de formato ainda estava disponível em tipos anuláveis.

outis nihil
fonte
3

pode ser que é apenas seguir o padrão? ou eles não conhecem o back-end. você está certo o código é exatamente o mesmo. você pode até fazer:

int? i = null;
i.ToString(); //No NullReferenceException
Andrey
fonte
Pode ser necessário seguir o caminho longo se ToString () precisar ser de cultura invariável, pois os anuláveis ​​não o possuem em seus menus.
Ε Г И І И О
1

int?é o açúcar da sintaxe que simplifica a declaração da variável anulável. É o mesmo que Nullable<int>.

Portanto, se você der uma olhada na implementação do ToString()método para Nullable<T> (veja abaixo) , poderá notar que ele retorna uma string vazia, caso não tenha valor.

public struct Nullable<T> where T : struct
{
    public override string ToString()
    {
      if (!this.hasValue)
        return "";
      return this.value.ToString();
    }
}

O que o MSDN diz:

Método Nullable.ToString

Retorna a representação de texto do valor do objeto Nullable atual se a propriedade HasValue for verdadeira ou uma sequência vazia ("") se a propriedade HasValue for falsa.

Portanto, o código a seguir imprimirá uma string vazia no console, em vez de lançar uma ArgumentNullExceptionexceção.

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
Aliaksei Maniuk
fonte