L’utilisation de «var» affectera-t-elle les performances?

Auparavant, j’ai posé une question sur la raison pour laquelle tant d’exemples utilisent le mot – clé var et obtenu la réponse que même s’il est nécessaire pour les types anonymes, il est néanmoins utilisé pour accélérer l’écriture du code et

En suivant ce lien (“C # 3.0 – Var Is not Objec”), j’ai vu que var est compilé au bon type dans l’IL (vous le verrez au milieu de l’article).

Ma question est de savoir combien le code IL utilise le mot-clé var , le cas échéant, et serait-il même proche d’un niveau mesurable sur les performances du code s’il était utilisé partout?

Il n’y a pas de code IL supplémentaire pour le mot-clé var : l’IL résultant doit être identique pour les types non-anonymes. Si le compilateur ne peut pas créer cet IL car il ne peut pas déterminer quel type vous souhaitez utiliser, vous obtenez une erreur de compilation.

La seule astuce est que var va déduire un type exact où vous avez peut-être choisi une interface ou un type parent si vous deviez définir le type manuellement.


Mise à jour 8 ans plus tard

Je dois mettre à jour ceci car ma compréhension a changé. Je pense maintenant que var peut affecter les performances dans le cas où une méthode retourne une interface, mais vous auriez utilisé un type exact. Par exemple, si vous avez cette méthode:

 IList Foo() { return Enumerable.Range(0,10).ToList(); } 

Considérez ces trois lignes de code pour appeler la méthode:

 List bar1 = Foo(); IList bar = Foo(); var bar3 = Foo(); 

Les trois comstacknt et exécutent comme prévu. Cependant, les deux premières lignes ne sont pas exactement les mêmes et la troisième ligne correspondra à la seconde plutôt qu’au premier. Étant donné que la signature de Foo() doit renvoyer un IList , le compilateur va créer la variable bar3 .

Du sharepoint vue de la performance, vous ne remarquerez surtout pas. Cependant, il existe des situations où les performances de la troisième ligne peuvent ne pas être aussi rapides que celles du premier . Comme vous continuez à utiliser la variable bar3 , le compilateur peut ne pas être capable de bar3 les appels de méthode de la même manière.

Notez qu’il est possible (probablement même) que la gigue puisse effacer cette différence, mais ce n’est pas garanti. En règle générale, vous devriez toujours considérer la var comme un facteur non significatif en termes de performances. Ce n’est certainement pas du tout comme l’utilisation d’une variable dynamic . Mais dire que cela ne fait jamais une différence peut être exagéré.

Comme le dit Joel, le compilateur fonctionne au moment de la compilation quel type devrait être var, en fait, il s’agit simplement d’une astuce que le compilateur effectue pour enregistrer les frappes, par exemple

 var s = "hi"; 

est remplacé par

 ssortingng s = "hi"; 

par le compilateur avant qu’une IL ne soit générée. L’IL généré sera exactement le même que si vous aviez tapé chaîne.

Comme personne n’a encore parlé de réflecteur …

Si vous comstackz le code C # suivant:

 static void Main(ssortingng[] args) { var x = "hello"; ssortingng y = "hello again!"; Console.WriteLine(x); Console.WriteLine(y); } 

Ensuite, utilisez le réflecteur, vous obtenez:

 // Methods private static void Main(ssortingng[] args) { ssortingng x = "hello"; ssortingng y = "hello again!"; Console.WriteLine(x); Console.WriteLine(y); } 

Donc, la réponse est clairement pas de performance à l’exécution!

Pour la méthode suivante:

  private static void SsortingngVsVarILOutput() { var ssortingng1 = new Ssortingng(new char[9]); ssortingng ssortingng2 = new Ssortingng(new char[9]); } 

La sortie IL est la suivante:

  { .method private hidebysig static void SsortingngVsVarILOutput() cil managed // Code size 28 (0x1c) .maxstack 2 .locals init ([0] ssortingng ssortingng1, [1] ssortingng ssortingng2) IL_0000: nop IL_0001: ldc.i4.s 9 IL_0003: newarr [mscorlib]System.Char IL_0008: newobj instance void [mscorlib]System.Ssortingng::.ctor(char[]) IL_000d: stloc.0 IL_000e: ldc.i4.s 9 IL_0010: newarr [mscorlib]System.Char IL_0015: newobj instance void [mscorlib]System.Ssortingng::.ctor(char[]) IL_001a: stloc.1 IL_001b: ret } // end of method Program::SsortingngVsVarILOutput 

Donc, pour être clair, c’est un style de codage paresseux. Je préfère les types natifs, étant donné le choix; Je vais prendre un peu de “bruit” pour m’assurer que j’écris et que je lis exactement ce que je pense être à l’heure du code / du débogage. * haussement d’épaules *

Le compilateur C # déduit le vrai type de la variable var au moment de la compilation. Il n’y a pas de différence dans l’IL généré.

Je ne pense pas que vous avez bien compris ce que vous lisez. S’il est compilé au bon type, il n’y a pas de différence. Quand je fais ceci:

 var i = 42; 

Le compilateur sait que c’est un int et génère du code comme si j’avais écrit

 int i = 42; 

Comme le poste que vous avez associé indique, il est compilé dans le même type. Ce n’est pas une vérification à l’exécution ou autre chose nécessitant un code supplémentaire. Le compilateur ne fait que déterminer le type et doit l’utiliser.

Il n’y a pas de coût d’exécution au moment d’utiliser var. Cependant, je soupçonne qu’il y a un coût de performance de compilation car le compilateur doit déduire le type, même si cela sera probablement négligeable.

Si le compilateur peut faire des inférences de type automatique, il n’y aura aucun problème de performance. Les deux généreront le même code

 var x = new ClassA(); ClassA x = new ClassA(); 

Cependant, si vous construisez le type dynamicment (LINQ …) alors var est votre seule question et il existe un autre mécanisme à comparer afin de déterminer quelle est la pénalité.

J’utilise toujours le mot var dans les articles web ou les guides.

La largeur de l’éditeur de texte de l’article en ligne est petite.

Si j’écris ceci:

 SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName(); 

Vous verrez que le texte de pré-code rendu ci-dessus est trop long et sort de la boîte, il est caché. Le lecteur doit faire défiler vers la droite pour voir la syntaxe complète.

C’est pourquoi j’utilise toujours le mot-clé var dans les écritures d’articles Web.

 var coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName(); 

Le pré-code rendu complet tient simplement dans l’écran.

En pratique, pour déclarer un object, j’utilise rarement var, je compte sur intellisense pour déclarer l’object plus rapidement.

Exemple:

 SomeCoolNamespace.SomeCoolObject coolObject = new SomeCoolNamespace.SomeCoolObject(); 

Mais, pour retourner un object à partir d’une méthode, j’utilise var pour écrire du code plus rapidement.

Exemple:

 var coolObject = GetCoolObject(param1, param2); 

“var” est une de ces choses que les gens aiment ou détestent (comme les régions). Cependant, contrairement aux régions, var est absolument nécessaire lors de la création de classes anonymes.

Pour moi, var a du sens lorsque vous modifiez un object directement comme:

 var dict = new Dictionary(); 

Cela étant dit, vous pouvez facilement faire:

Dictionary dict = new et intellisense rempliront le rest pour vous ici.

Si vous souhaitez uniquement travailler avec une interface spécifique, vous ne pouvez utiliser var que si la méthode que vous appelez renvoie directement l’interface.

Resharper semble être du côté de l’utilisation de “var” partout, ce qui peut pousser plus de gens à le faire de cette façon. Mais je suis en quelque sorte d’accord pour dire qu’il est plus difficile à lire si vous appelez une méthode et que ce qui est renvoyé par le nom n’est pas évident.

var lui-même ne ralentit pas les choses, mais il y a une mise en garde à ce sujet à laquelle peu de gens pensent. Si vous faites var result = SomeMethod(); ensuite, le code suivant attend une sorte de résultat où vous appelleriez diverses méthodes ou propriétés, etc. Si SomeMethod() changé sa définition en un autre type mais que celui-ci respectait toujours le contrat attendu par l’autre code, vous venez de créer un bogue vraiment désagréable (si aucun test d’unité / d’intégration, bien sûr).