J'ai une structure qui (pour les besoins de cette question) imite à peu près le type construit dans Point
.
Je dois vérifier qu'il a été instancié avant de l'utiliser. Quand c'était Point
, je pouvais faire ceci:
if (this.p == null)
Mais cela génère maintenant l'erreur suivante:
L'opérateur '==' ne peut pas être appliqué aux opérandes de type 'ProportionPoint' et '<null>'
Comment puis-je comparer mon struct avec null? Y at-il un autre moyen de vérifier l’instanciation?
struct
est un type de valeur - il n'est jamais nul.
Vous pouvez vérifier par rapport à default(ProportionPoint)
, qui est la valeur par défaut de la structure (par exemple zéro). Cependant, pour un point donné, il se peut que la valeur par défaut - l'origine - soit également une valeur "valide".
Au lieu de cela, vous pouvez utiliser un Nullable<ProportionPoint>
.
les structures sont des types de valeur et ne peuvent jamais être null contrairement aux types de référence. Vous pouvez vérifier par rapport à la valeur par défaut:
if (this.p.Equals(default(ProportionPoint)))
parce que p est struct, il n'est jamais nul, vous devez donc le comparer à sa valeur par défaut. Afin de vérifier l'équivalence entre votre valeur et la valeur dafault, . Si vous utilisez == vous obtiendrez
cannot be applied to operands of type 'ProportionPoint' and 'ProportionPoint' error
parce que les structures n'obtiennent pas une implémentation de == par défaut. vous devez donc surcharger les opérateurs == et! = dans votre structure comme ceci:
public static bool operator ==(firstOperand op1, secondOperand2 op2)
{
return op1.Equals(op2);
}
public static bool operator !=(firstOperand op1, secondOperand2 op2)
{
return !op1.Equals(op2);
}
et alors :
if (this.p == default(ProportionPoint))
une autre option consiste à utiliser directement Equals:
f (this.p.Equals.default(ProportionPoint))
Utilisez un nullable:
ProportionPoint? p1 = null;
if (p1 == null) ...
ou
if (!p1.HasValue) ...
Un struct ne peut pas être null. C'est un type value, pas un type de référence. Vous devez vérifier les propriétés avec les valeurs par défaut. Quelque chose comme:
if(p.X == 0 && p.Y == 0)
Une structure ne peut jamais être nulle, vous ne pouvez donc pas la comparer à nulle. Et une structure est toujours initialisée - si ce n'est par vous, alors par le compilateur avec les valeurs par défaut.
Contrairement à une variable ou à la valeur d’un type de référence, qui est un référence à zéro ou une instance de ce type, une variable ou valeur de struct est une instance de struct. Si on a un bloc de code qui commence par {Point myPoint; ...}
et que rien dans le bloc ne se ferme sur MyPoint
(la fermeture se produit quand il y a un yield return
dans un bloc, ou quand une méthode lambda ou anonyme utilise une variable d'un bloc englobant), Une instance de Point
commencera à exister avant que l'exécution n'entre dans le bloc et pourra cesser d'exister à tout moment après que l'exécution aura quitté le bloc. Dans tout contexte où l'on peut utiliser une variable de type struct, la structure existe.
La raison pour laquelle tous les types de structure sont considérés comme ayant un constructeur par défaut à ne rien faire est que ces types de structure sont créés de manière implicite. Quand on exécute une instruction comme Point[] myPoints = new Point[100];
, il crée un tableau rempli de 100 structures Point
; dans le processus, les instances de point 100
remplies à zéro sont mises en place instantanément. En C++, si un type a un constructeur, créer un tableau de ce type appellera le constructeur sur chaque élément du tableau en séquence avant qu'un code ne soit autorisé à accéder au tableau de manière temporaire. Si une exception est levée lors de la construction d'un élément, le code généré par le compilateur exécute le destructeur déterministe sur chaque élément créé avec succès avant l'évaporation du tableau. Bien que ce soit une fonctionnalité très puissante, son inclusion dans .net aurait considérablement compliqué le Framework.
J'ai créé une méthode d'extension qui ne fonctionne qu'avec des structures:
public static bool IsNull<T>(this T source) where T:struct
{
return source.Equals(default(T));
}
Convention d'appel:
if(myStruct.IsNull())
DoSomething();
Je comprends que ce n’est pas vraiment vérifier si c’est null
. Cependant, si je lui donnais un nom plus précis, par exemple IsEmpty
ou IsDefault
, dans six mois, j'oublierais que c'est là et, en voyant la liste des méthodes disponibles, ne la choisissez pas. Ce n'est pas techniquement un chèque nul; mais conceptuellement, ça l'est.