Réponses:
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
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);
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
|| Model.Model2.Model3.Model4.Name == null à la même logique, sinon dans le cas Model.Model2.Model3.Model4.Nameest null, mapped.Nameresteranull
Model.Model2.Model3.Model4.Nameest - null.
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
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: