Je travaille sur les applications développées en C # /. NET avec Visual Studio. Très souvent Resharper, dans les prototypes de mes méthodes, me conseille de remplacer le type de mes paramètres d'entrée avec des plus génériques. Par exemple, liste <> avec iEnumerable <> Si je n'utilise que la liste avec un foreach dans le corps de ma méthode. Je peux comprendre pourquoi il a l'air plus intelligent d'écrire cela, mais je suis assez préoccupé par la performance. Je crains que la performance de mes applications diminuait si j'écoute si j'écoute Resharber ...
Quelqu'un peut-il m'expliquer précisément (plus ou moins) ce qui se passe dans les coulisses (c'est-à-dire dans le CLR) lorsque j'écris: P > et quelle est la différence avec: p>
10 Réponses :
En général, la flexibilité accrue vaudra la différence de performance mineure qu'elle inciterait. P>
La raison de base de cette recommandation crée une méthode qui fonctionne sur ienumberable ou la liste est une flexibilité future. Si, à l'avenir, vous devez créer une myspecialstringsCollection, vous pourriez avoir la mise en œuvre de la méthode iEnumerable et utiliser toujours la même méthode. P>
Essentiellement, je pense que cela revient, à moins que vous remarquiez une performance significative et significative frappé (et que je serais choqué si vous remarquez); Préférez une interface plus tolérante, cela acceptera plus que ce que vous attendez aujourd'hui. P>
Vous devrez regarder le code généré pour être certain, mais dans ce cas, je doute qu'il y ait beaucoup de différence. La relève foreach em> fonctionne toujours sur un iEnumerable ou ienumerable ienumerable
En fait, la déclaration de forach ne nécessite pas i> nécessite un iNeuble ou iEnumerable
De plus, si l'utilisateur a une meilleure façon de faire des choses si elle est donnée une liste
Bien qu'ils soient habituellement mieux à vérifier que IList
@Jon: Je ne savais jamais ça. J'ai toujours pensé qu'il utilise l'interface. Connaissez-vous des exemples de types qui ont un getenumerator () qui renvoie quelque chose avec un mouvement movenext / courant, mais qui n'est pas iEnumerable / ienumerator?
Dans la première version (iEnumerable), il est plus générique et vous dites que la méthode accepte tout argument qui implémente cette interface. P>
deuxième version YO restreint la méthode pour accepter le type de classe SEPCIFIC et cela n'est pas recommandé du tout. Et la performance est la plupart des mêmes identiques. P>
Vous êtes inquiet pour la performance - mais avez-vous des motifs pour cette préoccupation? Je suppose que vous n'avez pas préparé le code du tout. toujours em> référence avant de remplacer le code lisible et nettoyer avec un code plus performant. P>
Dans ce cas, l'appel à Pendant que je soupçonne qu'il peut y avoir une différence théorique em> de performances entre l'utilisation de Ce n'est même pas comme si le type de séquence est utilisé pour de nombreuses opérations - il y a un seul appel à Ignorer l'analyse cependant, la chose à emporter est de mesurer em> performance avant de baser les décisions de codage à ce sujet. P>
Quant à ce qui se passe dans les coulisses - vous devez creuser dans les détails profonds de ce qui est exactement ce qui est dans les métadonnées de chaque cas. Je soupçonne que dans le cas d'une interface, il y a un niveau supplémentaire de la redirection, au moins en théorie - le CLR devrait déterminer où dans le type d'objet cible la machine à livres pour console.writeline code> dominera toute la performance de toute façon. P>
list ienumerable getenumerator () code> qui est déclaré pour retourner ienumerator ienumerable
En effet - en particulier dans les applications du monde réel où si vous faites quelque chose avec des réseaux, des bases de données ou des disques, il est très peu probable que quelque chose comme celui-ci soit votre problème de performance.
Ok peut-être que le fait que je donne un exemple concret cache ma vraie question. Et peut-être que ma question n'était pas la bonne. En fait, je suis plus curieux du mécanisme du CLR que de la performance en soi; De toute évidence, lorsque vous écrivez des tonnes de code, l'utilisation systématique de types et d'interfaces les plus génériques ne devrait pas être la chose qui coûte le plus cher.
En fait, vous pouvez obtenir une amélioration de la performance lorsque vous utilisez des interfaces. Comme CLR effectuant la mise en cache sur des appels d'interface - chose qu'elle ne fonctionnera pas sur des appels réguliers.
@Divan: Pourriez-vous donner plus de détails?
Optimisation non documentée du JIT. Méthode d'interface Dispatchers essaie de jouer intelligemment. D'ici
Une interface définit simplement la présence et la signature des méthodes publiques et des propriétés mises en œuvre par la classe. Étant donné que l'interface ne "se tiendra-t-elle pas", il devrait y avoir aucune différence de performance de la méthode elle-même et toute pénalité "casting" - si cela devrait être presque trop petit à mesurer. p>
La définition de la liste donc L'interface code> iEnumerable Expose la méthode Il s'ensuit que, si list iliste < / code>, icollection code>, ilist icollection ienumerable code> et iEnumerable getenumerator code> qui renvoie un ienumerator code >, un movenext code> méthode et une propriété code> actuelle code>. Ces mécanismes sont ce que la catégorie list ilist, icollection, ilist iEnumerable code> ou ienumerable
Il n'y a pas de pénalité de performance pour un statique. C'est une construction logique dans le texte du programme. P>
Comme les autres personnes ont dit, l'optimisation prématurée est la racine de tout mal. Écrivez votre code, exécutez-le dans une analyse Hotspot avant de vous inquiéter des choses sur le réglage des performances. P>
Obtenir IEnumerable <> pourrait créer des problèmes, comme vous pouvez recevoir une expression LINQ avec une exécution différente ou une déclaration de rendement. Dans les deux cas, vous n'aurez pas de collection mais quelque chose em> vous pouvez itérer. Donc, lorsque vous souhaitez définir des limites, vous pouvez demander un tableau. Il n'y a pas de problème à appeler collection.Tearray () em> avant de passer le paramètre, mais vous serez sûr qu'il n'y a pas de mises en garde dissolues cachées. P>
En général, je dirais que si vous remplacez l'interface non générique équivalente par la saveur générique (disons Un point de vente unique est que, contrairement à Java, .NET n'utilise pas l'effacement de type et em> prend en charge les types de valeur true ( Un repère synthétique braindead a été présenté: p> à être plus rapide par un facteur de 3.2x fort> que l'équivalent semi-équivalent non générique: p> Disclaimer strong> Je me rends compte La référence est synthétique, elle ne se concentre pas réellement sur l'utilisation d'interfaces em> à droite (plutôt directement des appels de méthodes virtuelles sur un type spécifique), etc. Cependant, il illustre le point que je fais. ne craignez pas les génériques strong> (du moins pas pour des raisons de performance). p> p> IList <> code> -> ilist struct code>), l'une des principales différences serait être dans la façon dont il stocke, par exemple une liste
Ok, je sais que c'est une très vieille discussion, mais peut-être que tout ce qui me frappe comme moi chercher de l'aide sur le même problème. En effet, il y a une pénalité de performance dans l'utilisation d'interfaces et, d'une certaine manière, je n'ai jamais eu deviné. Je mets une description ici (désolé: allemand) dans mon blog: jochen.jochen-manns.de/index.php/2011/02/05/...
@JMS: J'ai adoré cet article (malheureusement, tout le monde ne sera pas en mesure de le lire puisqu'il est en allemand). Cela va montrer que la complexité fait pour l'imprévisibilité. C'est aussi un excellent exemple de ce que Jon Skeet appelle
que vous devrez creuser dans les détails profonds de la compréhension [...] floue de la jitting, de la poignée, des vtables et de la manière dont ils appliquent code> etc.