246 votes

Pourquoi la valeur par défaut du type chaîne de caractères est-elle nulle au lieu d'être une chaîne vide ?

C'est assez ennuyeux de tester toutes mes chaînes pour null avant de pouvoir appliquer en toute sécurité des méthodes comme ToUpper() , StartWith() etc...

Si la valeur par défaut de string soit une chaîne vide, je n'aurais pas à effectuer de test, et je trouverais cela plus cohérent avec les autres types de valeurs tels que int o double par exemple. En outre, Nullable<String> aurait un sens.

Alors pourquoi les concepteurs de C# ont-ils choisi d'utiliser null comme valeur par défaut des chaînes de caractères ?

Note : Ceci concerne cette question mais il est plus axé sur le pourquoi que sur le comment.

57 votes

Considérez-vous que c'est un problème pour autre les types de référence ?

21 votes

@JonSkeet Non, mais seulement parce que j'ai initialement, à tort, pensé que les chaînes de caractères sont des types de valeurs.

24 votes

@Marcel : C'est une assez bonne raison de s'interroger sur ce sujet.

342voto

Habib Points 93087

Pourquoi la valeur par défaut du type chaîne de caractères est-elle nulle au lieu d'être vide ? vide ?

Parce que string est un type de référence et la valeur par défaut pour tous les types de référence est null .

C'est assez ennuyeux de tester toutes mes chaînes de caractères pour null avant de pouvoir appliquer en toute sécurité des méthodes comme ToUpper(), StartWith() etc...

Cela est cohérent avec le comportement des types de référence. Avant d'invoquer leurs membres d'instance, on devrait mettre en place une vérification pour une référence nulle.

Si la valeur par défaut de string était la chaîne vide, je n'aurais pas de tester, et j'aurais l'impression que c'est plus cohérent avec les autres types de valeurs comme int ou double par exemple.

Attribution de la valeur par défaut à un type de référence spécifique autre que null le rendrait incohérent .

En outre, Nullable<String> aurait un sens.

Nullable<T> fonctionne avec les types de valeurs. Il convient de noter que Nullable n'a pas été introduite sur la version originale du Plate-forme .NET donc il y aurait eu beaucoup de code cassé s'ils avaient changé cette règle.( Avec l'aimable autorisation de @jcolebrand )

0 votes

Mais la chaîne de caractères a un support spécial dans plusieurs domaines (littéraux de chaîne de caractères), ce qui aurait pu être implémenté (facilement).

10 votes

@HenkHolterman On pourrait implémenter une tonne de choses, mais pourquoi introduire une incohérence aussi flagrante ?

4 votes

@delnan - "pourquoi" était la question ici.

41voto

Dave Markle Points 44637

Habib a raison, car string est un type de référence.

Mais plus important encore, vous Ne le fais pas. doivent vérifier null à chaque fois que vous l'utilisez. Vous devriez probablement lancer un ArgumentNullException si quelqu'un passe à votre fonction un null référence, cependant.

Voilà le truc le cadre de travail lancerait un NullReferenceException pour vous de toute façon si vous avez essayé d'appeler .ToUpper() sur une chaîne de caractères. Rappelez-vous que ce cas peut toujours se produire même si vous testez vos arguments pour null puisque toute propriété ou méthode sur les objets passés en paramètre à votre fonction peut être évaluée à null .

Ceci étant dit, la vérification des chaînes vides ou des nuls est une chose courante à faire, et ils fournissent donc String.IsNullOrEmpty() y String.IsNullOrWhiteSpace() dans ce but.

33 votes

Vous ne devez jamais lancer un NullReferenceException vous-même ( msdn.microsoft.com/fr/us/library/ms173163.aspx ) ; vous lancez un ArgumentNullException si votre méthode ne peut pas accepter des refs nuls. De plus, les références nulles sont typiquement l'une des exceptions les plus difficiles à diagnostiquer lorsque vous corrigez des problèmes, donc je ne pense pas que la recommandation de ne pas vérifier les nullités soit très bonne.

4 votes

@Andy "Les NullRef's sont typiquement l'une des exceptions les plus difficiles à diagnostiquer" Je ne suis pas du tout d'accord, si vous enregistrez les choses, c'est vraiment facile à trouver et à corriger (il suffit de gérer le cas nul).

6 votes

Lancer ArgumentNullException présente l'avantage supplémentaire de pouvoir fournir le nom du paramètre. Pendant le débogage, cela permet de gagner... euh, des secondes. Mais des secondes importantes.

24voto

Tim Schmelter Points 163781

Vous pourriez écrire un méthode d'extension (pour ce que ça vaut) :

public static string EmptyNull(this string str)
{
    return str ?? "";
}

Maintenant, cela fonctionne en toute sécurité :

string str = null;
string upper = str.EmptyNull().ToUpper();

113 votes

Mais s'il vous plaît, ne le faites pas. La dernière chose qu'un autre programmeur souhaite voir, ce sont des milliers de lignes de code parsemées de .EmptyNull() partout, juste parce que le premier type avait "peur" des exceptions.

17 votes

@DaveMarkle : Mais de toute évidence, c'est exactement ce que le PO recherchait. "C'est assez ennuyeux de tester toutes mes chaînes de caractères pour vérifier qu'elles ne sont pas nulles avant de pouvoir appliquer en toute sécurité des méthodes comme ToUpper(), StartWith() etc."

20 votes

Le commentaire s'adressait à l'OP, pas à vous. Bien que votre réponse soit clairement correcte, un programmeur qui pose une question de base comme celle-ci devrait être fortement mis en garde contre la mise en pratique de votre solution dans le monde entier, comme c'est souvent le cas. Il y a un certain nombre de compromis dont vous ne parlez pas dans votre réponse, comme l'opacité, la complexité accrue, la difficulté de refactoring, la surutilisation potentielle des méthodes d'extension, et oui, les performances. Parfois (souvent), une réponse correcte n'est pas le bon chemin, et c'est pourquoi j'ai fait des commentaires.

14voto

Nerrve Points 1772

Les chaînes vides et les nulles sont fondamentalement différentes. Un null est l'absence d'une valeur et une chaîne vide est une valeur qui est vide.

Le langage de programmation qui fait des suppositions sur la "valeur" d'une variable, dans ce cas une chaîne vide, sera aussi bien que d'initialiser la chaîne avec toute autre valeur qui ne causera pas de problème de référence nulle.

De plus, si vous transmettez le gestionnaire de cette variable chaîne à d'autres parties de l'application, ce code n'aura aucun moyen de valider si vous avez intentionnellement transmis une valeur vide ou si vous avez oublié de remplir la valeur de cette variable.

Un autre cas où cela peut poser problème est celui où la chaîne est une valeur de retour d'une fonction. Puisque la chaîne est un type de référence et qu'elle peut techniquement avoir une valeur nulle ou vide, la fonction peut aussi techniquement retourner une valeur nulle ou vide (rien ne l'empêche de le faire). Maintenant, puisqu'il y a 2 notions de "l'absence de valeur", c'est-à-dire une chaîne vide et un null, tout le code qui consomme cette fonction devra faire 2 vérifications. Une pour empty et l'autre pour null.

En bref, il est toujours bon d'avoir une seule représentation pour un seul État. Pour une discussion plus large sur les vides et les nuls, voir les liens ci-dessous.

https://softwareengineering.stackexchange.com/questions/32578/sql-empty-string-vs-null-value

NULL vs Empty dans le traitement des entrées utilisateur

2 votes

Et comment voyez-vous exactement cette différence, disons dans une zone de texte ? L'utilisateur a-t-il oublié d'entrer une valeur dans le champ, ou le laisse-t-il délibérément vide ? Dans un langage de programmation, le terme "nul" a une signification spécifique : il n'est pas attribué. Nous savons qu'il n'a pas de valeur, ce qui n'est pas la même chose qu'un null de base de données.

1 votes

Il n'y a pas beaucoup de différence lorsque vous l'utilisez avec une zone de texte. Dans tous les cas, il est essentiel de disposer d'une notation pour représenter l'absence d'une valeur dans une chaîne de caractères. Si je devais en choisir une, je choisirais null.

0 votes

Dans Delphi, la chaîne est un type de valeur et ne peut donc pas être nulle. Cela rend la vie beaucoup plus facile à cet égard - je trouve vraiment très ennuyeux de faire de string un type de référence.

5voto

Henk Holterman Points 153608

Parce qu'une variable de type chaîne est un référence et non un instance .

Il aurait été possible de l'initialiser à Empty par défaut, mais cela aurait introduit beaucoup d'incohérences dans tout le système.

3 votes

Il n'y a pas de raison particulière string devrait être un type de référence. Pour être sûr, les caractères réels qui composent la chaîne doivent certainement être stockés sur le tas, mais compte tenu de la quantité de support dédié que les chaînes ont déjà dans le CLR, il ne serait pas exagéré d'avoir System.String être un type de valeur avec un seul champ privé Value de type HeapString . Ce champ serait un type de référence et aurait la valeur par défaut suivante null mais un String struct dont Value était nul se comporterait comme une chaîne vide. Le seul inconvénient de cette approche serait...

1 votes

...que le casting d'un String a Object entraînerait, en l'absence de code de cas particulier dans le runtime, la création d'une boîte String sur le tas, plutôt que de simplement copier une référence à l'objet HeapString .

1 votes

@supercat - personne ne dit que la chaîne de caractères devrait/pourrait être un type de valeur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X