Que signifie point d'interrogation et opérateur point? signifie en C # 6.0?

359

Avec C # 6.0 dans l'aperçu VS2015, nous avons un nouvel opérateur ?., qui peut être utilisé comme ceci:

public class A {
   string PropertyOfA { get; set; }
}

...

var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
   //somecode
}

Qu'est-ce que cela fait exactement?

Landeeyo
la source

Réponses:

500

C'est l' opérateur conditionnel nul . Cela signifie essentiellement:

"Évaluez le premier opérande; s'il est nul, arrêtez avec un résultat nul. Sinon, évaluez le deuxième opérande (en tant qu'accès membre du premier opérande)."

Dans votre exemple, le fait est que si aest null, alors a?.PropertyOfAévaluera nullplutôt que de lever une exception - il comparera alors cette nullréférence avec foo(en utilisant la ==surcharge de la chaîne ), trouvera qu'elles ne sont pas égales et l'exécution ira dans le corps de l' ifinstruction .

En d'autres termes, c'est comme ça:

string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
    ...
}

... sauf que cela an'est évalué qu'une seule fois.

Notez que cela peut également changer le type de l'expression. Par exemple, réfléchissez FileInfo.Length. C'est une propriété de type long, mais si vous l'utilisez avec l'opérateur conditionnel nul, vous vous retrouvez avec une expression de type long?:

FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
Jon Skeet
la source
8
N'est-il pas appelé l' opérateur conditionnel nul ?
SLaks
1
@SLaks: Je pensais que c'était "null conditionnel" mais je peux me tromper. La dernière fois que j'ai vérifié les documents sur les fonctionnalités du langage Roslyn, ils n'avaient pas été renommés non plus. Peut-être que la source est l'autorité ici - vérifiera.
Jon Skeet
3
@SLaks: Bien sûr. Dans SyntaxKind, c'est apparemment ConditionalAccessExpression qui n'est ennuyeusement aucun d'eux ...
Jon Skeet
12
j'ai préféré le nom d'opérateur "Elvis": P
Ahmed ilyas
3
Pour mémoire, j'ai vu cinq noms différents pour cet opérateur: navigation sécurisée, null-conditionnel, propagation nulle, accès conditionnel, Elvis.
Gigi
81

Il peut être très utile lors de l'aplatissement d'une hiérarchie et / ou du mappage d'objets. Au lieu de:

if (Model.Model2 == null
  || Model.Model2.Model3 == null
  || Model.Model2.Model3.Model4 == null
  || Model.Model2.Model3.Model4.Name == null)
{
  mapped.Name = "N/A"
}
else
{
  mapped.Name = Model.Model2.Model3.Model4.Name;
}

Il peut être écrit comme (même logique que ci-dessus)

mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";

Exemple de travail DotNetFiddle.Net .

(l' opérateur ?? ou null-coalescing est différent de l' opérateur conditionnel? ou null ).

Il peut également être utilisé en dehors des opérateurs d'affectation avec Action. Au lieu de

Action<TValue> myAction = null;

if (myAction != null)
{
  myAction(TValue);
}

Il peut être simplifié pour:

myAction?.Invoke(TValue);

Exemple DotNetFiddle :

en utilisant le système;

public class Program
{
  public static void Main()
  {
    Action<string> consoleWrite = null;

    consoleWrite?.Invoke("Test 1");

    consoleWrite = (s) => Console.WriteLine(s);

    consoleWrite?.Invoke("Test 2");
  }
}

Résultat:

Test 2

Erik Philips
la source
27
Pour sauver les gens qui recherchent ce que ?? est .. Il s'agit de l'opérateur de coalescence nulle et renverra Name s'il n'est pas nul, sinon il renverra "N / A".
Steve
6
@Erik Philips Je pense que vous devez ajouter || Model.Model2.Model3.Model4.Name == null à la même logique, sinon dans le cas Model.Model2.Model3.Model4.Nameest null, mapped.Nameresteranull
RazvanR
2
@ErikPhilips Pas sur la même page, je suppose. S'il vous plaît essayer de voir ce qui se passe dans les deux cas , votre cas Model.Model2.Model3.Model4.Nameest - null.
RazvanR
1
Le résultat est "N / A", encore une fois, VEUILLEZ LIRE LE PREMIER COMMENTAIRE. Exemple de travail DotNetFiddle.Net .
Erik Philips
7
@ErikPhilips: Cela n'a rien à voir avec le premier commentaire, car cela ne concerne pas votre premier exemple. En cela, vous elsesauteriez dans la branche-et avez mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null, tandis que votre deuxième exemple se substituerait à mapped.Name = "N/A". Voir l' édition DotNetFiddle
derM
3

Ceci est relativement nouveau pour C #, ce qui nous permet d'appeler facilement les fonctions par rapport aux valeurs nulles ou non nulles dans le chaînage de méthode.

ancienne façon de réaliser la même chose était:

var functionCaller = this.member;
if (functionCaller!= null)
    functionCaller.someFunction(var someParam);

et maintenant cela a été rendu beaucoup plus facile avec juste:

member?.someFunction(var someParam);

Je vous recommande fortement de le lire ici:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

Zeeshan Adil
la source