28 votes

Portée des variables en C #

J'ai une question pour vous les gars sur le code C# écrit: J'ai eu une longue discussion avec un collègue de la mine: Il dit que par la déclaration et de la initilizing toutes les variables en début de fonction de rendre le code plus lisible et rapide.

Merci de me donner au moins une saine raison pour laquelle il pourrait être de droite.

1. Il n'est pas facile à lire que si vous avez une longue fonction, vous devez avoir d'énormes déclaration de portée après intialization portée, donc c'est beaucoup plus facile de déclarer la variable que vous avez besoin, là où vous en avez besoin, de sorte que vous verrez devant vous.

2. Il n'est pas absolument plus rapide, que vous allouer la mémoire nécessaire et la pompe de la pile de fonction.

Ce pseudo-code exemple la mienne:

public void A(double dParam) 
{         
    if(... condition ... ) {
        double dAnotherParam;
        string sParam; 
        ...
        // use local scope vars here
     }   
}

Le Pseudo-code exemple lui:

public void A(double dParam) 
{
    double dAnotherParam;
    string sParam; 

    dAnotherPatam = 0; 
    sParam = null;     

    if(... condition ... ) {
        ...
    }                   
 }

Toutes les idées sur le sujet?

Je vous remercie à l'avance.

28voto

Reed Copsey Points 315315

Il semble que votre collègue est un ancien programmeur C. Il a utilisé pour être que vous avez eu à placer toutes vos variables au début de la portée, et les gens se sont habitués à faire de cette façon.

En C#, il est préférable de les placer à la portée là où ils sont nécessaires. Cela a quelques avantages, notamment:

  • Vous réduisez le risque d'erreur à partir de la réutilisation d'une variable de façon inappropriée, en particulier au cours de l'entretien à long terme
  • Vous êtes en gardant la variable contrainte à l'intérieur de ce champ d'activité, ce qui facilite le refactoring

Le dernier point est, à mon avis, le plus important. Bonne maintenabilité et de la testabilité compter sur la abiltiy pour garder vos méthodes de petite et de garder les variables déclarées comme ils sont utilisés rend l'extraction d'une méthode beaucoup, beaucoup plus simple. Non seulement les outils de devenir plus efficace, le résultat automatique de refactorings ont tendance à être plus simples (comme la variable n'est pas passé par ref, etc).


Comme pour ton exemple de code - personnellement, je ferais autrement que de vous. Vous êtes toujours déclarer votre variable au début de l'intérieur de la portée. Je n'aurais pas besoin de les déclarer jusqu'à ce qu'elles soient effectivement utilisées:

public void A(double dParam) 
{         
    if(... condition ... ) {
        double dAnotherParam = GetValueFromMethod();

        // use local scope vars here

        // Later, as needed:
        string sParam = dAnotherParam.ToString(); 
     }   
}

Déclarant en haut de la portée (même à l'intérieur de la portée), de nouveau, réduit la capacité de refactorisation automatique des outils d'extraction de méthodes que de besoin.

18voto

Bruno Brant Points 3590

C'est une affaire de style. Mes remarques:

  1. Si le bloc de code est petit, à la fin il n'a pas d'importance où vous placez la déclaration. Cependant, il est préférable d'avoir de déclarations plus proche de l'utilisation, principalement dans les grands blocs de code. Tout d'abord, de cette façon vous pouvez vous assurer que la variable n'est pas modifiée jusqu'à ce point dans le bloc, et la seconde, parce que vous pouvez vérifier le type et l'initialisation de la variable la plus rapide.

  2. D'ailleurs, son plus rapide de code en déclarant des variables près de l'endroit où vous les utilisez -- vous n'avez pas à revenir en arrière pour le début de la portée tout à déclaré oublié variable et puis revenir.

  3. Ce n'est pas plus rapide ou plus lent. Variables, n'importe où déclarée dans le champ d'application, verront leur allocation et initialisation centrée au début de la portée. Ceci peut être vérifié par la génération de IL pour la langue.

Par exemple, le code:

static void Main(string[] args)
{
    var a = 3;

    if (a > 1)
    {
        int b = 2;
        a += b;
    }

    var c = 10;
    Console.WriteLine(a + c);   
 }

Génère la suite IL:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       24 (0x18)
  .maxstack  2
  .locals init ([0] int32 a,     // Declare a
           [1] int32 b,          // Declare b
           [2] int32 c)          // Declare c
  IL_0000:  ldc.i4.3             
  IL_0001:  stloc.0              
  IL_0002:  ldloc.0              
  IL_0003:  ldc.i4.1             
  IL_0004:  ble.s      IL_000c
  IL_0006:  ldc.i4.2
  IL_0007:  stloc.1
  IL_0008:  ldloc.0
  IL_0009:  ldloc.1
  IL_000a:  add
  IL_000b:  stloc.0
  IL_000c:  ldc.i4.s   10
  IL_000e:  stloc.2
  IL_000f:  ldloc.0
  IL_0010:  ldloc.2
  IL_0011:  add
  IL_0012:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0017:  ret
} // end of method Program::Main

Une chose importante à noter est que les variables internes étendues, telles que la variable b, qui était à la si la portée est déclaré à la portée de la méthode par le compilateur.

Espérons que cela aide.

5voto

Bronumski Points 5754

Déclaration des variables au sommet d'une méthode est très old school et les accrocher au-dessus de C. on m'a appris c'est exactement la même chose à l'Université.

De nos jours, nous nous efforçons de maintenir des méthodes très petit et maigre, avec de sens paramètre et noms de méthode. Il est beaucoup plus propre à déclarer et initialiser une variable à l'intérieur de l'étendue dans laquelle il va être utilisé. Si il ya beaucoup de ces zones de code dans une méthode donnée, il peut être une indication que vous devriez refactoriser à petits plus facile de méthodes de lecture.

La seule fois où je voudrais envisager de le faire c'est quand vous voulez initialiser quelque chose à l'intérieur d'un try catch instruction enfin où vous voulez faire quelque chose avec l'objet dans le catch ou le bloc finally.

SomeObject someObject = null;

try
{
    someObject = GetSomeObject();
    return someObject.DoSomething();
}
finally
{
    if (someObject != null) someObject.DoSomethingElse();
}

La plupart du temps, tout ce que vous voulez faire est de nettoyer l'objet, donc, à l'aide d'instruction est plus que suffisantes, mais il y a des moments où il est nécessaire.

4voto

RedFilter Points 84190

En termes du code de s'exécuter plus rapidement avec toutes les variables déclarées au début de la routine, je dirais que le ci-contre est le cas, si il n'y a aucune différence. Je ne suis pas un expert sur ce sujet, mais je suppose que la collecte des ordures sera plus efficace en déclarant des variables à la plus faible portée, vous pouvez. De cette façon, le nettoyage peut se produire plus tôt.

En outre, en mettant les variables de près le code qui les utilise, il améliore la lisibilité de l'OMI.

Une analogie est qu'elle est la différence entre avoir des notes en marge (mettre juste à côté du texte que vous lisez), contre un mur de notes de bas de page au bas de la page (vous n'êtes pas sûr de ce que la note de bas de page se rapporte à ce texte sans faire quelques croix-référencement vous-même).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X