2015-08-24 1 views
3

J'ai eu le code suivant, qui fonctionne très bien:Pourquoi l'opérateur null-conditionnel se comporte-t-il différemment pour == et .Equals()?

var firstChild = token.First as JProperty; 
bool isHref = token.Children().Count() == 1 
      && firstChild?.Name == "href"; 

Je voulais faire la comparaison de chaînes de la casse, donc je l'ai changé:

var firstChild = token.First as JProperty; 

bool isHref = token.Children().Count() == 1 
      && firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase); 

Maintenant, le compilateur me donne un erreur:

Operator && cannot be applied to operands of type 'bool' and 'bool?'

Je peux corriger l'erreur par coalescent false comme

bool isHref = token.Children().Count() == 1 
     && (firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase) ?? false); 

Mais je suis curieux de savoir pourquoi le compilateur n'aime pas la première syntaxe null-conditionnelle.

+2

Et si vous faites 'String.Equals (firstChild? .Name," href ", StringComparison.OrdinalIgnoreCase);'? – Habib

+1

La raison en est que '? .' renverra soit 'null' soit la valeur, dans notre cas, puisqu'il y a une méthode return' bool', elle ne peut retourner que 'Nullable ' pour accommoder 'true/false' pour result ou 'null' dans le cas où' firstChild' est null. D'où le type de retour d'expression est 'Nullable ' et puisque vous ne pouvez pas appliquer '&&' sur les deux, donc l'erreur. – Habib

+1

Notez que vous pouvez utiliser '&' avec 'bool' et' bool? '. Il en résultera un 'bool? ' '&&' ne fonctionne pas à cause du court-circuit. Le court-circuit ne fonctionne pas parce que vous voulez un résultat de 'null' si le' bool? 'Est' null', mais vous n'évalueriez même pas la deuxième partie si la première partie était 'false'. – juharr

Répondre

5

Simplifions-nous à l'essentiel.

string x = null, y = null; 

// this is null. b1 is bool? 
var b1 = x?.Equals(y); 

// b2 is bool 
// this is true, since the operator doesn't require non-null operands 
var b2 = x == y; 

Fondamentalement, .Equals() requiert un objet non nul pour fonctionner. C'est différent de ==, qui est lié statiquement, pas distribué de façon dynamique.

+0

Merci, c'est l'explication que je cherchais! –

2

la première expression renvoie null ou bool

si firstChild est nulle, alors la valeur de retour sera nul et il ne peut pas être utilisé dans une condition if

firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase) 

sera le même que

firstChild == null ? null : firstChild.Name.Equals("href", StringComparison.OrdinalIgnoreCase) 
+0

Cela a du sens, mais cela n'explique toujours pas pourquoi '&& firstChild? .Name ==" href "' compile bien. –

+3

le résultat de firstChild? .Name est nul ou une chaîne et puis il se compare à "href" qui résulte à seulement une valeur true/false – Khatibzadeh