Le nul de fusionner opérateur est beaucoup plus clair lors de la vérification de null, c'est son but principal. Il peut également être enchaînés.
object a = null;
object b = null;
object c = new object();
object d = a ?? b ?? c; //d == c.
Alors que l'opérateur est limitée à la valeur null de la vérification, l'opérateur ternaire est pas. Par exemple
bool isQuestion = true;
string question = isQuestion ? "Yes" : "No";
Je pense que les gens ne sont pas conscients de la valeur null fusionnent opérateur afin qu'ils utiliser l'opérateur ternaire à la place. Ternaire existait avant C# dans la plupart des C style de langues, de sorte si vous ne savez pas C# à l'intérieur et à l'extérieur et/ou que vous avez programmé dans une autre langue, ternaire est un choix naturel. Si vous êtes à la vérification de la valeur null si, utilisez la valeur null fusionnent opérateur, il est conçu pour cela, et IL est légèrement optimisé (comparer ?? pour un if then else).
Voici un exemple de comparaison de l'utilisation de chaque
object a = null;
object b = null;
object c = null;
object nullCoalesce = a ?? b ?? c;
object ternary = a != null ? a : b != null ? b : c;
object ifThenElse;
if (a != null)
ifThenElse = a;
else if (b != null)
ifThenElse = b;
else if (c != null)
ifThenElse = c;
Tout d'abord, il suffit de regarder la syntaxe pour les nuls fusionnent, c'est plus clair. Ternaire est vraiment déroutant. Regardons maintenant le IL
Null Fusionnent Seulement
.entrypoint
.maxstack 2
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object nullCoalesce)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: dup
L_000c: brtrue.s L_0015
L_000e: pop
L_000f: ldloc.1
L_0010: dup
L_0011: brtrue.s L_0015
L_0013: pop
L_0014: ldloc.2
L_0015: stloc.3
L_0016: ldloc.3
L_0017: call void [mscorlib]System.Console::WriteLine(object)
L_001c: ret
Ternaire Seulement
.entrypoint
.maxstack 2
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object ternary)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: brtrue.s L_0016
L_000d: ldloc.1
L_000e: brtrue.s L_0013
L_0010: ldloc.2
L_0011: br.s L_0017
L_0013: ldloc.1
L_0014: br.s L_0017
L_0016: ldloc.0
L_0017: stloc.3
L_0018: ldloc.3
L_0019: call void [mscorlib]System.Console::WriteLine(object)
L_001e: ret
Si Alors Sinon Seulement
.entrypoint
.maxstack 1
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object ifThenElse)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: brfalse.s L_0011
L_000d: ldloc.0
L_000e: stloc.3
L_000f: br.s L_001a
L_0011: ldloc.1
L_0012: brfalse.s L_0018
L_0014: ldloc.1
L_0015: stloc.3
L_0016: br.s L_001a
L_0018: ldloc.2
L_0019: stloc.3
L_001a: ldloc.3
L_001b: call void [mscorlib]System.Console::WriteLine(object)
L_0020: ret
IL n'est pas un de mes points forts, peut-être que quelqu'un peut éditer ma réponse et d'étendre sur elle. Je vais expliquer ma théorie, mais je préfère ne pas confondre moi et pour les autres. Le nombre de LOC est similaire pour tous les trois, mais pas tous, IL exploitants de prendre la même longueur de temps à s'exécuter.