Question

Je défini le struct suivant:

public struct Call
{
    public SourceFile caller;
    public SourceFile callee;

    public Call(SourceFile caller, SourceFile callee)
    {
        this.caller = caller;
        this.callee = callee;
    }
}

Plus tard, je cède à la propriété d'un autre objet Tag:

line.Tag = new Call(sf1, sf2);

Mais lorsque je tente de récupérer la propriété Tag comme si,

Call call = line.Tag as Call;

Visual Studio donne l'erreur suivante-compilation:

  

L'opérateur doit être utilisé dans un   Type de référence ou de type Nullable

Quelle est la signification de cela? Et comment puis-je résoudre?

Était-ce utile?

La solution

A struct est un type de valeur, donc il ne peut pas être utilisé avec l'opérateur as. L'opérateur as doit être en mesure d'attribuer une valeur nulle si la distribution échoue. Ceci est possible uniquement avec un type de référence ou un type de valeur nullable.

Il y a deux manières de résoudre ce problème, mais votre meilleur pari est de changer votre type de Call d'un struct à une classe. Cela modifiera le type d'un type de valeur à un type de référence, ce qui permet à l'opérateur de as d'attribuer une valeur nulle si la distribution échoue.

Pour plus d'informations sur les types de valeur par rapport à des types de référence, ce est un article décent. En outre, un coup d'oeil sur MSDN:

Autres conseils

Certaines des réponses existantes ne sont pas tout à fait à droite. Vous ne pouvez pas utiliser non nullables avec les types as, parce que le résultat de as est la valeur nulle du type si le premier opérande est pas réellement d'un type approprié.

Cependant, vous peut utiliser as avec des types de valeur ... si elles sont nullable:

int a = 10;
object o = a;

int? x = o as int?; // x is a Nullable<int> with value 10
long? y = o as long?; // y is a Nullable<long> with the null value

Vous peut utilisation:

Call? call = line.Tag as Call?;

Ensuite, vous pouvez l'utiliser comme:

if (call != null)
{
    // Do stuff with call.Value
}

Deux mises en garde cependant:

  • Dans mon expérience, c'est plus lent que d'utiliser simplement is suivi d'un casting
  • Vous devriez revoir sérieusement votre type actuel de Call:
    • Il est expose les champs publics, ce qui est généralement l'encapsulation pauvre
    • Il est un type de valeur mutables, ce qui est presque certainement une erreur

Je vous suggère fortement de faire une classe au lieu -. À quel point ce problème disparaît de toute façon

Une autre pensée: si l'étiquette doit toujours un Call, alors il est préférable de le jeter:

Call call = (Call) line.Tag;

De cette façon, si les données ne correspond pas à vos attentes (c.-à il y a un bug tel que le Tag n'est pas un Call), vous arrivez à découvrir tôt, plutôt que après avoir fait potentiellement un autre travail. Notez que cette distribution se comportera différemment selon que Call est un struct ou une classe, si Tag est nulle - vous pouvez lancer une valeur nulle à une variable d'un type de référence (ou un type de valeur nullable), mais pas à un non type valeur nullable.

De C # Spec

  

§7.10.11 L'opérateur as est utilisé pour   convertir explicitement une valeur à une donnée    type de référence ou type Nullable . Contrairement à une expression de casting   (§7.7.6), l'opérateur comme ne lève jamais   une exception. Au lieu de cela, si le   conversion indiqué est possible,   la valeur résultante est null .

Les références et les types nullables peuvent être nuls. Stucts sont les types de valeur afin qu'ils ne peuvent pas être nuls.

Call? call = line.Tag as Call?;

Il est une limitation de C #. Si le type était un type de référence, si le casting n'a pas il serait tout simplement revenir « nul », mais comme il est un type de valeur, il ne sait pas quoi revenir lorsque le sort échoue.

Vous devez remplacer votre utilisation comme avec deux: « est » et « comme »

if (line.Tag is Call) {
  call = (Call)line.Tag;
} else {
  // Do whatever you would do if as returned null.
}

Quelle est la signification - Comme indiqué, les structures sont des types de valeur

.

Comment puis-je résoudre - Changer à

Call call = line.Tag;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top