33 votes

Pourquoi C # a-t-il besoin de parenthèses lors de l'utilisation de valeurs nuls

Je suis nouveau dans C # et en explorant les fonctionnalités du langage, je suis tombé sur quelque chose d'étrange:

 struct Foo
{
    public Foo Identity() { return this; }

    public static void Bar(Foo? foo)
    {
        Foo foo1 = foo?.Identity().Value; // Does not compile
        Foo foo2 = (foo?.Identity()).Value; // Compiles
    }
}
 

Quelqu'un pourrait-il m'expliquer pourquoi les parenthèses sont nécessaires?

40voto

D Stanley Points 54768

Quelqu'un pourrait-il m'expliquer pourquoi les parenthèses sont nécessaires?

Parce qu' Identity() renvoie un Foo (pas un Foo?) et n'a donc pas d' Value de la propriété. Si foo est null, null propage à travers l' Identity appel.

Lorsque vous mettez entre parenthèses, le résultat de l' expression est un Nullable<Foo> qui n' ont Value de la propriété.

Notez également que si foo est null, alors vous serez en appelant Value sur Nullable<Foo> qui n'a pas de valeur, et obtenez une exception au moment de l'exécution. Certains analyseurs statiques de reconnaître que vous avez une possible null exception référence en attente de se produire et vous avertir.

Si vous développez à leurs équivalents sans nul propagation ça sera plus clair:

Foo foo1;
if(foo != null)
{
    foo1 = foo.Identity().Value;  // not possible - Foo has no Value property.
}
else
{
    foo1 = null;  // also not possible 
}

Foo foo2;
Foo? temp;
if(foo != null)
{
    temp = foo.Identity();
}
else
{
   temp = null;  // actually a Nullable<Foo> with no value
}
foo2 = temp.Value;  // legal, but will throw an exception at run-time if foo is null

Si Identity() retours Foo, pourquoi est - Foo foo3 = foo?.Identity(); compile pas ?

L'équivalent de:

Foo foo3
if(foo != null)
{
    foo3 = foo.Identity();
}
else
{
    foo3 = null;  // not possible 
}

0voto

user3185569 Points 22924

Je pense que c'était une bonne décision de la part de l'équipe c#, de faire de cette façon. Examiner le dessous de scénario:

Si la structure est :

struct Foo
{
    public int ID { set; get; }

    public Foo Identity() { return this; }

    public static void Bar(Foo? foo)
    {
        int? foo1 = foo?.Identity().ID; // compile
        Foo foo2 = (foo?.Identity()).Value; // Compiles
    }
}

Si vous n'avez pas besoin de la parenthèse pour accéder à la Nullable conséquent, vous ne seriez pas en mesure d'accéder à l' ID de la propriété. Depuis la ci-dessous ne compile pas:

int? foo2 = (foo?.Identity()).GetValueOrDefault()?.ID

Lorsque vous écrivez foo?.Identity(). qu'est-ce que après l' . est de type Foo retournée par Identity(). Cependant, en (foo?.Identity()). qu'est-ce que après l' . est Foo? qui est le résultat réel de l'ensemble de l'énoncé foo?.Identity().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X