Comment puis-je vérifier si une structure a été instanciée?
J'ai une structure qui (aux fins de cette question) imite à peu près le type Point
intégré.
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 ' '
Comment puis-je comparer ma structure à null? Existe-t-il un autre moyen de vérifier l'instanciation?
10 réponses
Un struct
est un type de valeur: il n'est jamais nulle.
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, il se peut que la valeur par défaut - l'origine-soit également une valeur" valide".
À la place, vous pouvez utiliser un Nullable<ProportionPoint>
.
Les structures sont des types de valeur et elles ne peuvent jamais être nulles 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 ne sera jamais null, Vous devriez 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. si vous avez besoin de surcharger l' == et != opérateurs 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);
}
Puis :
if (this.p == default(ProportionPoint))
Une autre option consiste à utiliser Equals directement:
f (this.p.Equals.default(ProportionPoint))
Une structure ne peut pas être nulle . C'est un type de valeur , 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 null, donc vous ne pouvez pas la comparer à null. Et une structure est toujours initialisée-sinon par vous, puis par le compilateur avec des valeurs par défaut.
Utiliser un nullable:
ProportionPoint? p1 = null;
if (p1 == null) ...
Ou
if (!p1.HasValue) ...
, Contrairement à une variable ou une valeur d'un type de référence, qui est un référence soit à zéro ou à un cas de ce type, une structure d'une variable ou une valeur est une struct exemple. Si l'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 lorsqu'il y a un yield return
dans un bloc, ou lorsqu'une méthode lambda ou anonyme utilise une variable d'un bloc englobant), alors une instance de Point
existera quelque temps avant entre dans le bloc, et peut cesser d'exister à tout moment après l'exécution quitte le bloc. Dans n'importe quel 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 do-nothing est que les types de structure existent implicitement. Quand on exécute une instruction comme Point[] myPoints = new Point[100];
, il crée un tableau rempli de zéro de 100 Point
structures; dans le processus, 100
instances de Point rempli de zéro viennent instantanément dans l'existence. En C++, si un type a un constructeur, la création d'un tableau de ce type appellera le constructeur sur chaque élément du tableau en séquence avant que n'importe quel code n'ait accès au tableau pendant un certain temps. Si une exception est levée lors de la construction d'un élément, le code généré par le compilateur exécutera le destructeur déterministe sur chaque élément qui a été créé avec succès avant que le tableau lui-même ne s'évapore. Bien que ce soit une fonctionnalité très puissante, y compris dans. NET aurait considérablement compliqué le Cadre.
J'ai fait 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 qu'il ne vérifie pas vraiment si c'est null
. Cependant, si je lui donnais un nom plus précis, comme IsEmpty
ou IsDefault
, dans six mois, j'oublierais qu'il est là et en voyant la liste des méthodes disponibles, Je ne le choisirais pas. Ce n'est pas techniquement une vérification nulle; mais conceptuellement, c'est le cas.
Les variables de Structure ne peuvent pas être null, une option serait de le déclarer comme nullable.
Les structures ne peuvent pas être null, mais la solution de contournement de la vérification d'une structure par rapport à sa valeur par défaut peut donner un faux négatif si vous voulez réellement stocker des valeurs équivalentes aux valeurs par défaut à tout moment.
(Par exemple, une structure avec la valeur (0,0,0)
peut être intacte par défaut, ou peut-être stocker le point d'origine dans l'espace 3D.)
Une autre approche qui évite ce problème de faux négatif serait d'ajouter simplement une autre propriété à la structure - par exemple un bool ou int-pour suivre si données ont été stockées. Ensuite, tout constructeur qui initialise la structure avec des données réelles définit cette valeur sur true / 1. Dans la structure par défaut, cette valeur sera toujours false / 0, donc la vérification par rapport à default(MyStruct)
ne devrait jamais vous donner un faux négatif même si toutes les autres données stockées correspondent aux valeurs par défaut.
public Struct MyStruct {
public float x { get; private set; }
public bool initialized { get; private set; }
public MyStruct(float _x){
x=_x;
initialized = true;
}
}