6
votes

Ces 2 déclarations sont-elles identiques?

Les 2 extraits de code suivants obtiennent-ils la même chose?

Mon code d'origine: P>

public class Configuration
    {
        public string Name
        {
            get;
            set;
        }
        public string Value
        {
            get;
            set;
        }
    }


5 commentaires

Vous n'obtiendrez pas de NullReferenceEcepton depuis la première partie de l'instruction Safefilenames! = NULL COURT-CIRCUT OUT et vous n'allez jamais toucher convert.toboolean (Safefilenames .Value) - c'est la façon dont les && fonctionne.


Cela ne provoquerait pas une exception de référence nulle à cause de l'évaluation paresseuse de C #. La déclaration && est toujours évaluée le côté gauche puis le côté droit. Mais si le côté gauche est faux, cela ne prendra pas la peine d'évaluer le côté droit, car le résultat logique est déjà déterminé. Donc, si les noms de sécurité sont nuls, l'appel de convert.Tobolian n'est jamais fait. Ce genre de chose est assez courant dans le code.


Donc, si je comprends bien le && - si la partie gauche est fausse, elle renvoie false ... sinon elle évalue la bonne partie et renvoie le résultat de la droite?


C'est exactement raison. (Une chose similaire, mais opposée, chose se passe avec ||.)


@JL: Oui, c'est correct. C'est ce qu'on appelle l'évaluation du court-circuit. en.wikipedia.org/wiki/short-circuit_evaluation


8 Réponses :


5
votes

Les deux déclarations font exactement la même chose. Ce qui est à utiliser est une question de préférence, mais je préfère la version de Resharper. Plus concis, moins de pièces en mouvement. Plus facile de voir l'intention du code.


3 commentaires

Et si cela.safefilensamens est null? Essayer sûrement de convertir.Toboollean sur un null, causerait une exception de référence nulle?


@JL: la deuxième clause n'exécuterait jamais si les réalisations étaient nuls


Court-circuit pour la victoire.



1
votes

Ils sont les mêmes. The && est un opérateur de court-circuit de sorte que la seconde moitié de l'expression n'évaluera pas si les noms de téléfilène sont nuls.


0 commentaires

1
votes

Ils sont les mêmes. Dans la doublure, si la première condition échoue, la seconde n'est pas évaluée. Donc, vous n'obtenez pas une référence nulle.

Je parie que l'IL est la même dans les deux cas.

Je préfère la deuxième version.


0 commentaires

24
votes

Le fait que vous avez posé la question me suggère que le premier est préféré. C'est-à-dire que votre question me semble que votre question implique de croire que le premier code est plus facile à comprendre et que vous n'êtes pas tout à fait sûr si la seconde est équivalente. Un objectif principal de la conception du logiciel est de gérer la complexité. Si cela vous dérouissant maintenant, cela peut également être pour vous plus tard, ou à Whomever soutient votre code sur la route.


4 commentaires

Je suis entièrement d'accord, mais je vais le changer. Je pense que c'est quelque chose que chaque développeur .NET devrait savoir. Donc, je me sens un peu mal pour ne pas avoir connu ça .. Mais merci à tout le monde pour la bonne leçon ...


Cela s'est perdu dans tout mon poteau d'opérateur Null Coalesce et pour cela, je suis vraiment désolé. Très bonne réponse!


Une bonne réponse en effet, mais je vous recommanderais d'aller avec la méthode de Resharper puisque vous comprenez probablement ce qu'il est à propos de maintenant, et cela semble potentiellement plus rapide (compte tenu du support de court-circuit)


Ouais. Considérez que le pauvre shlub qui doit réparer votre code à 22h00 le vendredi avant le déploiement pourrait être vous mois à partir de maintenant. Laissez également suffisamment d'indices (commentaires) dans le code pour reconstruire votre réflexion sur la logique du programme.



2
votes

Il réduit la complexité cyclomatique de votre code en utilisant la suggestion de Resharber.

s'il est plus facile de lire ou non, est une opinion personnelle, mais je préfère la suggestion que Resharper vous a donné.

Ils sont identiques, et si vous voulez une lisibilité, je pourrais également suggérer les éléments suivants: xxx

ou xxx


3 commentaires

Remarque: éliminer les accolades à moi quand ils sont inutiles, le code rend pas meilleur, encore une fois, très opinion.


@Aaqutarium, votre réponse n'est pas incorrecte ou inefficace. C'est tout aussi excitant que les autres, je suppose. Vous voter.


C'est une opinion, mais il convient de noter que Stylecop signale cela comme une erreur. La cohérence est un facteur; L'autre introduit une erreur lorsque vous ajoutez votre deuxième instruction dans un IF (sans autre) et oubliez d'ajouter vos accolades aussi. L'IDE va ​​généralement l'indenter et vous en informera, mais si vous utilisez un bloc-notes visuelle ....



1
votes

Yep Les deux déclarations feront la même chose, vous n'avez pas à prendre des suggestions de re-showsers comme Evangile, ce qu'un homme considère comme un code lisible est un autre désordre des hommes.

Il y a quelques autres façons de Faites ce que vous essayez de faire cela pourrait être plus lisible, quel type de valeur est des noms de sécurité? On dirait que cela peut être un nullable bool? Si oui, vous pouvez simplement écrire, P>

this.SafeFileNames = safeFileNames.GetValueOrDefault();


0 commentaires

0
votes

logiquement, ils sont identiques. Toute différence de performance serait probablement néglicielle. Il est possible que la deuxième forme se traduise par un code binaire plus efficace sur certaines plates-formes puisque le deuxième formulaire s'éloigne avec un conditionnel. Les conditionnels (une exécution spéculative incorrecte) peuvent gâcher le pipeline d'instructions de votre CPU dans le travail intensif de la CPU. Cependant, l'IL et la gigue doivent émettre du code de qualité adéquat pour cela pour faire beaucoup de différence.

Je suis d'accord avec votre sens de la lisibilité, mais je ne suppose pas que tout le monde partage cela.


0 commentaires

5
votes

Voici il pour les deux morceaux de code. J'ai pris votre code et j'ai créé une application de console pour jeter un coup d'œil à l'IL. Comme vous pouvez le constater à partir de l'IL résultant, une méthode (méthode2) est de 4 octets plus courts, mais l'IL qui fonctionne pour les deux est à peu près la même chose, donc en ce qui concerne la performance. Ne vous inquiétez pas. Ils auront tous les deux la même performance. Concentrez-vous davantage sur lequel on est plus facile à lire et à mieux démontrer votre intention.

Mon code: P>

.method public hidebysig instance void  method2() cil managed
{
  // Code size       38 (0x26)
  .maxstack  1
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<bool> safeFileNames)
  IL_0000:  ldloca.s   safeFileNames
  IL_0002:  initobj    valuetype [mscorlib]System.Nullable`1<bool>
  IL_0008:  ldloca.s   safeFileNames
  IL_000a:  call       instance bool valuetype [mscorlib]System.Nullable`1<bool>::get_HasValue()
  IL_000f:  brfalse.s  IL_001f
  IL_0011:  ldloca.s   safeFileNames
  IL_0013:  call       instance !0 valuetype [mscorlib]System.Nullable`1<bool>::get_Value()
  IL_0018:  call       bool [mscorlib]System.Convert::ToBoolean(bool)
  IL_001d:  br.s       IL_0020
  IL_001f:  ldc.i4.0
  IL_0020:  call       void ConsoleApplication5.Program::set_SafeFileNames(bool)
  IL_0025:  ret
} // end of method Program::method2


2 commentaires

Si je pouvais donner cela plus d'un point que je ferais, j'adore quand les gens vérifient l'IL pour déterminer les différences réelles.


Semblait être une bonne excuse pour dépoussiérer l'ildas et jouer pendant un moment :-)