ToString nul ()

142

Je vois partout des constructions comme:

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

Pourquoi ne pas utiliser simplement:

string test = myVar.ToString();

N'est-ce pas exactement la même chose? Au moins Reflector dit que:

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

Alors, est-ce correct (la version plus courte) ou est-ce que je manque quelque chose?

IamDeveloper
la source
1
Je n'ai pas vu de code comme celui-ci :)
tymtam

Réponses:

112

Vous avez tout à fait raison. Toujours dans cette question , la première solution est suggérée alors que personne ne le remarque réellement ToString()donne déjà la bonne réponse.

Peut-être que l'argument pour la solution la plus verbeuse est la lisibilité: lorsque vous appelez ToString()quelque chose qui est censé être null, vous vous attendez généralement à un NullReferenceException, bien qu'ici il ne soit pas lancé.

Tomas Vana
la source
21
En fait, au moins deux personnes l'ont remarqué: Eric Lippert et Johannes Rössel.
Jon Skeet
7
Bien que je sois sûr que ce n'est pas ce que vous vouliez dire, la référence n'est pas réellement nulle ici. Nullable <T> est un type valeur. C'est pourquoi l'appel ToString()fonctionne sans que personne ne NullReferenceExceptionsoit jeté.
Thorarin
2
Si c'était la mentalité, vous vous attendriez .HasValueà toujours lever cette exception.
Extragorey
Une autre raison pour laquelle les gens utilisent la version verbeuse pourrait être pour la parité avec des expressions comme myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nulloù vous avez besoin de l'objet déballé pour accéder à la ToStringméthode souhaitée . Bien sûr, il existe une solution plus concise pour cela aussi:$"{myNullableDateTime:d}"
Extragorey
14

Je pense que beaucoup de gens ont de tels contrôles car ce n'est pas un comportement naturel d'un objet qui peut avoir une valeur nulle.

Andrew Bezzub
la source
@Andrew, d'accord, parce que les gens (comme moi) pensent d'abord que cela va jeter une exception.
Nathan Koop
1
Je n'avais aucune idée de ce comportement. J'aurais certainement pensé que toute construction qui renvoie true pour (x == null) lancerait également une exception NullReferenceException si vous appelez x.ToString ().
Dan Bryant
5

Non, vous avez raison, la version plus courte est la même que ce que d'autres personnes ont fait à cet égard. L'autre construction que j'ai tendance à utiliser beaucoup au lieu du ternaire avec nullables est l'opérateur de fusion nul ,. qui vous protège également des nulls. Pour ToString () ce n'est pas nécessaire (comme vous l'avez souligné) mais pour les valeurs int par défaut (par exemple) cela fonctionne bien, par exemple:

int page = currentPage ?? 1;

qui vous permet de faire toutes les opérations sur les entiers sur la page sans d'abord vérifier explicitement null et appeler la valeur dans currentPage (où currentPage est un int? peut-être passé comme paramètre)

Paul
la source
5

Je sais, longtemps après que c'était pertinent, mais ... je suppose que c'est parce que pour les types Nullable comme int? la méthode .ToString () ne vous permet pas d'utiliser des chaînes de format. Voir Comment puis-je formater un DateTime nullable avec ToString ()? . Peut-être que dans le code d'origine, il y avait une chaîne de format dans .ToString (), ou peut-être que le codeur a oublié que .ToString () sans la chaîne de format était toujours disponible sur les types Nullable.

outis nihil
la source
3

peut-être est-ce juste pour suivre le modèle? ou ils ne connaissent pas le backend. vous avez raison, le code est exactement le même. vous pouvez même faire:

int? i = null;
i.ToString(); //No NullReferenceException
Andreï
la source
Vous devrez peut-être emprunter la longue route si ToString () doit être de culture invariante, car les nullables ne l'ont pas dans leur menu.
Ε Г И І И О
1

int?est un sucre de syntaxe qui simplifie la déclaration d'une variable Nullable. C'est la même chose que Nullable<int>.

Donc, si vous regardez l'implémentation de la ToString()méthode pour Nullable<T> (voir ci-dessous) , vous pouvez remarquer qu'elle renvoie une chaîne vide au cas où elle n'aurait pas de valeur.

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

Ce que dit MSDN:

Nullable.ToString, méthode

Renvoie la représentation textuelle de la valeur de l'objet Nullable actuel si la propriété HasValue est true ou une chaîne vide ("") si la propriété HasValue est false.

Ainsi, le code suivant affichera une chaîne vide sur la console au lieu de lever une ArgumentNullExceptionexception.

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