Pourquoi voit-on souvent «null! = Variable» au lieu de «variable! = Null» dans C #?

Dans c #, y a-t-il une différence dans la vitesse d’exécution pour l’ordre dans lequel vous indiquez la condition?

if (null != variable) ... if (variable != null) ... 

Depuis peu, j’ai vu le premier assez souvent et cela a attiré mon attention depuis que j’étais habitué au second.

S’il n’y a pas de différence, quel est l’avantage du premier?

C’est un hold-up de C. Dans C, si vous utilisez un mauvais compilateur ou si les avertissements ne sont pas suffisamment élevés, cela comstackra sans aucun avertissement (et c’est bien le code légal):

 // Probably wrong if (x = 5) 

quand vous avez probablement signifié

 if (x == 5) 

Vous pouvez contourner ce problème en C en procédant comme suit:

 if (5 == x) 

Une faute de frappe entraînera un code invalide.

Maintenant, en C # c’est tout. Sauf si vous comparez deux valeurs booléennes (ce qui est rare, IME), vous pouvez écrire le code le plus lisible, car une instruction “if” nécessite une expression booléenne pour commencer, et le type ” x=5 ” est Int32 , pas Boolean

Je suggère que si vous voyez cela dans le code de vos collègues, vous les éduquez sur les manières de parler des langues modernes et leur suggéreriez d’écrire la forme la plus naturelle à l’avenir.

Il y a une bonne raison d’utiliser d’abord null: if(null == myDuck)

Si votre class Duck remplace l’opérateur == , alors if(myDuck == null) peut entrer dans une boucle infinie.

L’utilisation de null utilise d’abord un comparateur d’égalité par défaut et fait réellement ce que vous vouliez.

(J’entends que vous vous êtes habitué à lire le code écrit de cette façon finalement – je n’ai pas encore connu cette transformation).

Voici un exemple:

 public class myDuck { public int quacks; static override bool operator ==(myDuck a, myDuck b) { // these will overflow the stack - because the a==null reenters this function from the top again if (a == null && b == null) return true; if (a == null || b == null) return false; // these wont loop if (null == a && null == b) return true; if (null == a || null == b) return false; return a.quacks == b.quacks; // this goes to the integer comparison } } 

Je suppose que c’est un programmeur C qui a changé de langue.

En C, vous pouvez écrire ce qui suit:

 int i = 0; if (i = 1) { ... } 

Notez l’utilisation d’un seul signe égal, ce qui signifie que le code affectera 1 à la variable i, puis renverra 1 (une affectation est une expression) et utilisera 1 dans l’instruction if, qui sera considérée comme vraie. En d’autres termes, ce qui précède est un bug.

En C # cependant, ce n’est pas possible. Il n’y a en effet aucune différence entre les deux.

Comme tout le monde l’a déjà noté, cela vient plus ou moins du langage C où vous pourriez obtenir un faux code si vous oubliez accidentellement le deuxième signe égal. Mais il existe une autre raison qui correspond également à C #: Readability.

Prenons simplement cet exemple simple:

 if(someVariableThatShouldBeChecked != null && anotherOne != null && justAnotherCheckThatIsNeededForTestingNullity != null && allTheseChecksAreReallyBoring != null && thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded != null) { // ToDo: Everything is checked, do something... } 

Si vous souhaitez simplement échanger tous les mots nuls au début, vous pouvez facilement repérer tous les contrôles:

 if(null != someVariableThatShouldBeChecked && null != anotherOne && null != justAnotherCheckThatIsNeededForTestingNullity && null != allTheseChecksAreReallyBoring && null != thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded) { // ToDo: Everything is checked, do something... } 

Donc, cet exemple est peut-être un mauvais exemple (reportez-vous aux directives de codage), mais pensez simplement à faire défiler rapidement un fichier de code complet. En voyant simplement le modèle

 if(null ... 

vous savez immédiatement ce qui va arriver.

Si c’est le contraire, vous devez toujours parcourir la fin de la ligne pour voir le contrôle de la nullité, vous permettant de trébucher une seconde pour savoir quel type de vérification est effectué. Donc, peut-être que la coloration syntaxique peut vous aider, mais vous êtes toujours plus lent lorsque ces mots-clés se trouvent à la fin de la ligne au lieu de l’avant.

Autrefois, les gens oubliaient le ‘!’ (ou le “=” supplémentaire pour l’égalité, qui est plus difficile à repérer) et faire une affectation plutôt qu’une comparaison. mettre le null en tête élimine la possibilité du bug, puisque null n’est pas une valeur l (IE ne peut lui être assigné).

La plupart des compilateurs modernes émettent un avertissement lorsque vous effectuez une affectation dans un conditionnel de nos jours, et C # donne en fait une erreur. La plupart des gens ne font que suivre le schéma var == null car il est plus facile à lire pour certaines personnes.

Je ne vois aucun avantage à suivre cette convention. En C, où les types booléens n’existent pas, il est utile d’écrire

 if( 5 == variable) 

plutôt que

 if (variable == 5) 

parce que si vous oubliez l’un des signes d’égalisation, vous vous retrouvez avec

 if (variable = 5) 

qui atsortingbue 5 à variable et toujours évaluer à vrai. Mais en Java, un booléen est un booléen. Et avec! =, Il n’y a aucune raison.

Un bon conseil, cependant, est d’écrire

 if (CONSTANT.equals(mySsortingng)) 

plutôt que

 if (mySsortingng.equals(CONSTANT)) 

car cela aide à éviter les exceptions NullPointerExceptions.

Mon conseil serait de demander une justification de la règle. S’il n’y en a pas, pourquoi le suivre? Cela n’aide pas la lisibilité

Pour moi, c’est toujours le style que tu préfères

@Shy – Encore une fois, si vous confondez les opérateurs, alors vous devriez avoir une erreur de compilation ou vous exécuterez du code avec un bogue – un bogue qui revient et vous pique plus tard, car il a provoqué un comportement inattendu.

Encore une chose … Si vous comparez une variable à une constante (entier ou chaîne par exemple), il est conseillé de mettre la constante à gauche car vous ne rencontrerez jamais NullPointerExceptions:

 int i; if(i==1){ // Exception raised: i is not initialized. (C/C++) doThis(); } 

tandis que

 int i; if(1==i){ // OK, but the condition is not met. doThis(); } 

Maintenant, par défaut, C # instancie toutes les variables, vous ne devriez pas avoir ce problème dans cette langue.