Est-il préférable de déclarer une variable à l'intérieur ou à l'extérieur d'une boucle?
Est mieux de le faire:
variable1Type foo;
variable2Type baa;
foreach(var val in list)
{
foo = new Foo( ... );
foo.x = FormatValue(val);
baa = new Baa();
baa.main = foo;
baa.Do();
}
Ou:
foreach(var val in list)
{
variable1Type foo = new Foo( ... );
foo.x = FormatValue(val);
variable2Type baa = new Baa();
baa.main = foo;
baa.Do();
}
La question est: qui est le plus rapide 1 ou 2 cas?
La différence est insignifiante? Est-il le même dans les applications réelles?
Cela peut être une optimisation de micro, mais je veux vraiment savoir ce qui est mieux.
- Il n'y a pas de différence de performances si vous n'êtes pas la capture de la variable dans une expression lambda.
- Vous devriez valeur de la différence sémantique et non la différence de performances, qui dans ce cas n'est. En déclarant à l'intérieur de la boucle automatiquement vous savez qu'il est utilisé uniquement à l'intérieur de la boucle.
- Je déteste faire ça, mais -1: votre question n'est pas une indication de l'effort de recherche. Vous pourriez avoir certainement testé cela sur votre propre.
- Permettez-moi d'ajouter: - vous posez des questions à propos de la performance, afin de connaître la bonne façon. Dans ce cas (comme dans beaucoup d'autres) la bonne façon est de penser à d'autres choses que de la performance.
- Je dirais que, plus tard, le code est plus lisible
Vous devez vous connecter pour publier un commentaire.
En terme de Performance, nous allons essayer d'exemples concrets:
J'ai délibérément choisi une valeur de type et d'une référence de type dans le cas qui affecte les choses. Maintenant, le IL pour eux:
Comme vous pouvez le voir, en dehors de l'ordre sur la pile le compilateur qui s'est passé à choisir - qui pourrait tout aussi bien avoir été un ordre différent - il n'avait absolument aucun effet. À son tour, il n'y a vraiment pas quelque chose que l'on donne la gigue de faire beaucoup de l'utilisation de ce que l'autre n'est pas d'en donner.
Autre que cela, il est une sorte de différence.
Dans mon
Method1()
,x
etsb
sont limités à laforeach
, et ne peut être accédé que ce soit délibérément ou accidentellement en dehors d'elle.Dans mon
Method2()
,x
etsb
ne sont pas connus au moment de la compilation fiable d'attribuer une valeur à l'intérieur de laforeach
(le compilateur ne connaît pas leforeach
sera effectuer au moins une boucle), afin que l'utilisation de c'est interdit.Jusqu'à présent, pas de réelle différence.
Je peut toutefois affecter et utiliser
x
et/ousb
à l'extérieur de laforeach
. En règle générale, je dirais que c'est probablement une mauvaise détermination de la portée la plupart du temps, alors je serais favorable àMethod1
, mais je pourrais avoir quelques judicieux de raison de vouloir se référer à eux (de façon plus réaliste, si elles n'étaient pas non attribué), auquel cas j'irais pourMethod2
.Encore, c'est une question de comment le chaque code peut être étendu ou non, pas de différence au code écrit. Vraiment, il n'y a pas de différence.
Il n'a pas d'importance, il n'a pas d'effet sur les performances que ce soit.
La plupart vous diront à l'intérieur de la boucle qui fait le plus de sens.
C'est juste une question de portée. Dans ce cas, où foo et baa sont utilisés uniquement à l'intérieur de la boucle for, il est recommandé de les déclarer à l'intérieur de la boucle. C'est aussi plus sûr.
OK, j'ai répondu à cette question, sans se rendre compte où l'affiche originale a été la création d'un nouvel objet à chaque fois d'aller à travers la boucle et pas seulement 'l'aide' de l'objet. Alors, non, il ne devrait pas vraiment être un effet négligeable quand il s'agit de la performance. Avec cela, je voudrais aller avec la deuxième méthode et de déclarer l'objet à l'intérieur de la boucle. De cette façon, il sera nettoyé au cours de la prochaine GC passer et le maintient de l'objet dans le champ d'application.
--- Je vais laisser mon orignal réponse, juste parce que j'ai tapé tout ça, et ça pourrait aider quelqu'un d'autre qui cherche ce message plus tard. Je vous promets qu'à l'avenir, je ferai plus attention avant j'ai essayer de répondre à la question suivante.
Tim
En fait, je pense qu'il y a une différence. Si je me souviens bien, chaque fois que vous créez un nouvel objet
= new foo()
vous obtiendrez cet objet ajouté à la mémoire du tas. Donc, en créant les objets dans la boucle que vous allez ajouter à la surcharge du système. Si vous savez que la boucle va être petit, il n'est pas un problème.Donc, si vous vous retrouvez dans une boucle à dire 1000 objets, vous allez être la création de 1000 variables qui ne seront pas éliminés jusqu'à ce que la prochaine collecte de déchets. Maintenant, appuyez sur une base de données où vous voulez faire quelque chose et que vous avez plus de 20 000 lignes de travailler avec... Vous pouvez créer un système de demande en fonction de ce type d'objet que vous créez.
Ce devrait être facile à tester... Créer une application qui crée de 10 000 articles avec un horodatage quand vous entrez dans la boucle et lorsque vous quittez. La première fois que vous le faites, la déclaration de la variable avant la boucle et la prochaine fois au cours de la boucle. Vous pourriez avoir à bosse qui comptent beaucoup plus que 10K pour voir une réelle différence dans la vitesse mais.
Ainsi, il y a le problème de portée. Si elle est créée dans la boucle, il est passé une fois que vous sortir de la boucle, de sorte que vous ne pouvez pas y accéder de nouveau. Mais cela permet aussi de le nettoyer comme la collecte des ordures finira par jeter une fois sortie de la boucle.
Tim
string x;
variable sur la pile pour objet d'être affecté, mais aucun objet sur le tas.x = new string('a', 23);
maintenant, il y a un objet sur le tas.string a = x; string b = x; string c = x; string d = x;
4 plus variables, mais seulement un objet sur le tas.a = b = c = d = x = new string('b', 2);
un ou deux objets sur le tas comme la première chaîne sera GC avait à un certain point, mais nous ne savons pas exactement quand. Dans la question, les deux formes d'appelnew Foo()
etnew Baa()
le même nombre de fois. C'est qui qui utilise la mémoire du tas.Les deux sont tout à fait valable, pas sûr qu'il y a une "bonne" façon de faire cela.
Votre premier cas est le plus efficace de la mémoire (au moins dans le court terme). La déclaration des variables à l'intérieur de la boucle de la force, plus la redistribution de la mémoire; cependant, avec .Filets de garbage collector, comme ceux des variables hors de portée, ils seront nettoyés périodiquement, mais pas nécessairement immédiatement. La différence de vitesse est sans doute négligeable.
Le deuxième cas est en effet un peu plus sûr, comme limitant la portée de vos variables, autant que possible, est généralement de bonne pratique.
En JS l'allocation de mémoire est tout eachtime, En C#, il n'y a pas de différence, mais si la variable locale est capturé par une méthode anonyme comme la lambda expression, il n'aura d'importance.