Pourquoi la valeur par défaut du type string est-elle nulle au lieu d'une chaîne vide?

c'est assez ennuyeux de tester toutes mes cordes pour null avant que je puisse appliquer en toute sécurité des méthodes comme ToUpper() , StartWith() etc...

si la valeur par défaut de string était la chaîne vide, je n'aurais pas à le tester, et je le sentirais plus cohérent avec les autres types de valeurs comme int ou double par exemple. En outre Nullable<String> aurait du sens.

alors pourquoi les designers de C# ont-ils choisi utiliser null comme valeur par défaut de chaînes?

Note: il s'agit de cette question , mais est plus axée sur le pourquoi au lieu de ce qu'il faut en faire.

190
demandé sur Community 2013-01-15 16:17:11

14 réponses

pourquoi la valeur par défaut du type de chaîne est nulle au lieu de vide chaîne?

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 pour null avant que je puisse appliquez en toute sécurité des méthodes comme ToUpper (), StartWith (), etc...

That est compatible avec le comportement des types de référence. Avant d'invoquer leurs membres d'instance, on devrait mettre un check en place pour une référence nulle.

si la valeur par défaut de string était la chaîne vide, je n'aurais pas pour tester, et je le sentirais être plus cohérent avec l'autre les types de valeurs comme int ou double par exemple.

attribuant la valeur par défaut à un type de référence spécifique autre que null ce serait incohérent .

de plus Nullable<String> aurait du sens.

Nullable<T> fonctionne avec les types de valeur. Il est à noter que Nullable n'a pas été introduit sur la plate-forme originale .net donc il y aurait eu beaucoup de code brisé s'ils avaient changé cette règle.( courtoisie @jcolebrand )

280
répondu Habib 2017-05-23 12:18:01

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

Mais plus important encore, vous ne pas vérifier null chaque fois que vous l'utilisez. Vous devriez probablement jeter un ArgumentNullException si quelqu'un passe Votre fonction une référence null , cependant.

Voici la chose -- le cadre lancerait un NullReferenceException pour vous de toute façon si vous essayiez d'appeler .ToUpper() sur une corde. Rappelez-vous que ce cas peut encore se produire même si vous testez vos arguments pour null puisque n'importe quelle propriété ou méthode sur les objets passés à votre fonction comme paramètres peut évaluer à null .

cela dit, vérifier pour les cordes vides ou nulls est une chose courante à faire, donc ils fournissent String.IsNullOrEmpty() et String.IsNullOrWhiteSpace() à cette fin.

40
répondu Dave Markle 2014-08-21 21:07:42

vous pourriez écrire un méthode d'extension (pour ce que cela 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();
21
répondu Tim Schmelter 2014-06-11 19:23:16

les cordes vides et les nulls sont fondamentalement différents. Une valeur null est l'absence d'une valeur et une chaîne vide est une valeur qui est vide.

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

aussi, si vous passez la poignée à cette variable de chaîne à d'autres parties de la application, alors ce code n'aura aucun moyen de valider si vous avez intentionnellement passé une valeur vide ou vous avez oublié de peupler la valeur de cette variable.

une Autre occasion où ce serait un problème, c'est quand la chaîne est une valeur de retour d'une fonction. Puisque string est un type de référence et peut techniquement avoir une valeur comme null et vide les deux, donc la fonction peut aussi techniquement retourner un null ou vide (il n'y a rien pour l'arrêter de de le faire). Maintenant, puisqu'il y a 2 notions de "l'absence d'une valeur", I. e une chaîne vide et un null, tout le code qui consomme cette fonction devra faire 2 vérifications. Un pour vide et l'autre pour null.

bref, il est toujours bon de n'avoir qu'une seule représentation pour un seul État. Pour une discussion plus large sur empty et nulls, voir les liens ci-dessous.

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

nul vs vide lorsqu'il s'agit de l'entrée de l'utilisateur

14
répondu Nerrve 2017-05-23 12:18:01

vous pouvez également (à partir de VS2015 et du nouveau compilateur) utiliser le

string myString = null;
string result = myString?.ToUpper();

le résultat de la chaîne sera null.

12
répondu russelrillema 2018-01-10 10:20:48

parce qu'une variable string est une référence , pas une instance .

L'initialiser à vider par défaut aurait été possible mais il aurait introduit beaucoup d'incohérences partout sur le plateau.

5
répondu Henk Holterman 2013-01-15 12:18:17

pourquoi les concepteurs de C# ont choisi d'utiliser null comme valeur par défaut de les chaînes?

parce que les chaînes sont types de référence , les types de référence sont la valeur par défaut est null . Les Variables des types de référence stockent les références aux données réelles.

default mot-clé pour cette affaire;

string str = default(string); 

str est un string , c'est donc un type de référence , de sorte que la valeur par défaut est null .

int str = (default)(int);

str est un int , c'est donc un valeur type , de sorte que la valeur par défaut est zero .

5
répondu Soner Gönül 2013-01-15 12:28:08

la raison/problème fondamental est que les concepteurs de la spécification CLS (qui définit comment les langues interagissent avec .net) n'ont pas défini un moyen par lequel les membres de la classe pourraient spécifier qu'ils doivent être appelés directement, plutôt que par callvirt , sans que l'appelant n'effectue une vérification de référence nulle; il n'a pas non plus fourni une multitude de structures de définition qui ne seraient pas soumises à la boxe" normale".

si la spécification CLS définissait un tel moyen, il serait alors possible pour .net de suivre systématiquement l'exemple établi par le Common Object Model (COM), dans lequel une référence de chaîne nulle était considérée sémantiquement équivalente à une chaîne vide, et pour d'autres types de classe immuables définis par l'utilisateur qui sont censés avoir une sémantique de valeur pour définir également des valeurs par défaut. Essentiellement , ce qui se passerait serait pour chaque membre de String , par exemple Length d'être écrit comme quelque chose comme [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} } . Cette approche permettrait d' ont offert une très belle sémantique pour les choses qui devraient se comporter comme des valeurs, mais en raison de la mise en œuvre des questions doivent être stockées sur le tas. La plus grande difficulté avec cette approche est que la sémantique de la conversion entre de tels types et Object pourrait devenir un peu trouble.

une autre approche aurait été de permettre la définition de types de structures spéciales qui n'héritaient pas de Object , mais avaient plutôt boxe et unboxing personnalisés opérations (qui se convertiraient à/à partir d'un autre type de classe). Dans une telle approche, il y aurait un type de classe NullableString qui se comporterait comme string le fait maintenant, et un type de structure personnalisé String , qui contiendrait un seul champ privé Value de type String . Tenter de convertir un String en NullableString ou Object retournerait Value si non nul, ou String.Empty si nul. Essayer de lancer sur String , une référence non-nulle à un L'instance NullableString stockerait la référence dans Value (peut-être stockerait nul si la longueur était zéro); casting toute autre référence lancerait une exception.

même si les chaînes doivent être stockées sur le tas, il n'y a aucune raison conceptuelle pour qu'elles ne se se comportent comme des types de valeurs qui ont une valeur par défaut non nulle. Le fait de les stocker dans une structure "normale" contenant une référence aurait été efficace pour le code qui: utilisé comme type "string", mais aurait ajouté une couche supplémentaire de l'indirecte et l'inefficacité lors du moulage à"Objet". Bien que je ne prévois pas .net ajouter l'une ou l'autre des caractéristiques ci-dessus à cette date tardive, peut-être les concepteurs de cadres futurs pourraient envisager de les inclure.

5
répondu supercat 2013-01-15 16:55:12

si la valeur par défaut de string était la chaîne vide, je n'aurais pas à tester

faux! Changer la valeur par défaut ne change pas le fait que c'est un type de référence et quelqu'un peut encore explicitement mettre la référence à null .

de plus Nullable<String> aurait du sens.

vrai point. Il serait faites plus de sens de ne pas autoriser null pour n'importe quels types de référence, au lieu d'exiger Nullable<TheRefType> pour cette caractéristique.

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

cohérence avec d'autres types de référence. Maintenant, pourquoi autoriser null dans les types de référence? Probablement pour qu'il se sente comme C, même si c'est une décision de conception discutable dans un langage qui fournit également Nullable .

4
répondu Dan Burton 2013-01-15 16:26:00

peut-être que si vous utilisiez l'opérateur ?? pour assigner votre variable string, cela pourrait vous aider.

string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.
3
répondu Amen JLILI 2015-11-14 19:49:51

Une Chaîne de caractères est un objet immuable qui signifie que lorsque la valeur, ancienne valeur, n'obtient pas effacé de la mémoire, mais reste dans l'ancien emplacement, et la nouvelle valeur est mise dans un nouvel emplacement. Ainsi, si la valeur par défaut de String a était String.Empty , il serait gaspiller le bloc String.Empty en mémoire quand il a été donné sa première valeur.

bien qu'il semble minuscule, il pourrait se transformer en problème lors de l'initialisation d'un large tableau de chaînes avec des valeurs par défaut de String.Empty . Bien sûr, vous pouvez toujours utiliser la classe mutable StringBuilder si cela devait être un problème.

2
répondu djv 2013-01-15 19:11:09

puisque string est un type de référence et que la valeur par défaut pour le type de référence est nulle.

2
répondu Akshay 2013-01-15 21:09:09

peut-être que le mot-clé string vous a confondu, car il ressemble exactement à n'importe quel autre type de valeur déclaration, mais il est en fait un alias à System.String comme expliqué dans cette question .

Aussi la couleur bleu foncé dans Visual Studio et la première lettre minuscule peut induire en erreur en pensant qu'il s'agit d'un struct .

0
répondu Alessandro Da Rugna 2017-05-23 11:47:23
Les modèles

N'ont été annulables qu'à la version 2.0.

si les types nullables avaient été faits au début de la langue, string aurait été non-nullable et string? aurait été nullable. Mais ils n'ont pas pu le faire en raison de la rétrocompatibilité.

beaucoup de gens parlent de type ref ou pas TYPE ref, mais string est une classe hors de l'ordinaire et des solutions auraient été trouvées pour le rendre possible.

0
répondu Thomas Koelle 2015-02-17 15:11:16