Y a-t-il une pénalité, de sorte que vous ne devriez que les définir comme nullable lorsque vous en avez vraiment besoin? P>
merci p>
5 Réponses :
Quels types de valeur sont réellement nullables? Je ne connais aucun. P>
Edit: Si vous vous référez au type de chaîne, ce n'est pas un type de valeur, mais un type de référence. P>
Vous devez les envelopper dans le type NULLLABLE
Mais c'est quelque chose de différent alors. Je crois que le démarreur de la rubrique signifiait des types de valeur nullables hors de la boîte, faisant probablement référence au type de chaîne.
Je pense que l'op signifie quelque chose comme "si des types de valeur peuvent être nullables, pourquoi ne sont-ils pas tous nullables du début?".
Eh bien, beaucoup de programmeurs ne peuvent pas comprendre les concepts de pointeurs et de récursions, beaucoup seraient probablement confus si des types étaient tous nullables dès le début. Nullable
Oui, il y a une pénalité. La structure Bien que le booléen ne soit qu'un octeen, les structures sont alignées sur des limites des mots même. Un nullable
int code> utilise quatre octets de mémoire, mais un
int? Code> a besoin de huit octets. P>
La pénalité est bien pire qu'un mot supplémentaire. La conception de la structure nullable signifie que la création d'un nullable
nullable
diverses raisons: p>
nullable code> n'existait pas tant .net 2.0, et il ne peut pas casser le code existant - en particulier avec les différentes règles de boxe pour nullables Code> li>
- Signification: Si je veux un
INT code>, je ne suis peut-être pas veux strong> il est nullable ... je veux que ce soit un int code> , et je ne veux pas avoir à vérifier / gérer les nulls li>
- espace: il ajoute des coûts supplémentaires à chaque structure ... En particulier, imaginez un octet
[] code>, et considérez maintenant si octet code> a été nullable - beaucoup de frais généraux supplémentaires ; * Plus, cela vous empêcherait de faire blits em> strong> etc * li>
-
performance: nullable code> ajoute beaucoup de sanctions supplémentaires; En particulier, beaucoup d'appels cachés à .hasvalue code> et .value code> / .gevalueordfault () code>; Ceci est indiqué en particulier dans les "opérateurs levés" - c'est-à-dire x + y code> devient quelque chose comme ci-dessous, qui ajoute des boucles serrées, etc. p>
(x.hasvalue && y.hasvalue)? (x.gevalueordfault () + y.gevalueordordfault ()): null code> p> li>
ul>
De même, x == y code> doit vérifier: p>
- si Null => vrai li>
- si un null => faux li>
- Utilisez sinon utiliser
== code> sur getvalueordfault () code> de chaque li>
ul>
lots forts> de frais généraux .... p>
N'oubliez pas d'extra ?? opérateur, ils l'ont jeté aussi. int i = j ?? k; // Si j est null, utilisez k.
Eh bien, ce n'est pas spécifique au nullable
@Chris fait ce travail du tout? J ne peut pas être null, sinon vous ne pouvez pas l'affecter à un type de valeur, non? ;-)
@Erik - il peut si j code> est nullable (c'est-à-dire
int? Code>) et
k code> est non nullable (c.-à-d.
int code >)
Et vous serez foutu si vous utilisez des rayons de référence!
@Leppie - cela signifie tout type de valeur (non Boxed), bien que
En plus de Marc Gravell Répondre, vérifiez le code reflété de NULLABLABLE public struct Nullable<T> where T: struct
{
private bool hasValue;
internal T value;
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
public bool HasValue
{
get
{
return this.hasValue;
}
}
public T Value
{
get
{
if (!this.HasValue)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
}
return this.value;
}
}
public T GetValueOrDefault()
{
return this.value;
}
public T GetValueOrDefault(T defaultValue)
{
if (!this.HasValue)
{
return defaultValue;
}
return this.value;
}
public override bool Equals(object other)
{
if (!this.HasValue)
{
return (other == null);
}
if (other == null)
{
return false;
}
return this.value.Equals(other);
}
public override int GetHashCode()
{
if (!this.HasValue)
{
return 0;
}
return this.value.GetHashCode();
}
public override string ToString()
{
if (!this.HasValue)
{
return "";
}
return this.value.ToString();
}
public static implicit operator T?(T value)
{
return new T?(value);
}
public static explicit operator T(T? value)
{
return value.Value;
}
}
Considérez la mise en œuvre. Un entier en C # est défini comme une structure est stocké directement sur la pile, par opposition aux références d'objets qui sont des pointeurs à la mémoire (la référence elle-même est dans la pile, mais la répartition est Dans la pile). p> Une référence null signifie simplement que le pointeur de la pile n'a pas été initialisé à un emplacement dans le tas. P> P>