web-dev-qa-db-fra.com

Les méthodes C # qui * peuvent * être statiques doivent-elles être statiques?

Les méthodes C # qui peuvent être statiques doivent-elles être statiques?

Nous en discutions aujourd'hui et je suis un peu sur la clôture. Imaginez que vous ayez une longue méthode pour refactoriser quelques lignes. La nouvelle méthode prend probablement quelques variables locales de la méthode parente et renvoie une valeur. Cela signifie qu'il pourrait être statique.

La question est: devrait être statique? Ce n'est pas statique par conception ou par choix, simplement par sa nature en ce qu'il ne fait référence à aucune valeur d'instance.

102
Bernhard Hofmann

Ça dépend. Il existe en réalité 2 types de méthodes statiques:

  1. Méthodes statiques car elles PEUVENT l'être
  2. Méthodes statiques car elles DOIVENT être

Dans une base de code de petite à moyenne taille, vous pouvez vraiment traiter les deux méthodes de manière interchangeable.

Si vous avez une méthode qui est dans la première catégorie (peut être statique) et que vous devez la changer pour accéder à l'état de classe, il est relativement simple de déterminer s'il est possible de transformer la méthode statique en une méthode d'instance.

Dans une grande base de code, cependant, le nombre de sites d'appel peut rendre la recherche pour voir s'il est possible de convertir une méthode statique en une méthode non statique trop coûteuse. Plusieurs fois, les gens verront le nombre d'appels et diront "ok ... Je ferais mieux de ne pas changer cette méthode, mais d'en créer une nouvelle qui fait ce dont j'ai besoin".

Cela peut entraîner:

  1. Beaucoup de duplication de code
  2. Une explosion du nombre d'arguments de méthode

Ces deux choses sont mauvaises.

Donc, mon conseil serait que si vous avez une base de code supérieure à 200K LOC, je ne rendrais les méthodes statiques que si elles sont des méthodes incontournables.

Le refactoring de non statique à statique est relativement facile (il suffit d'ajouter un mot-clé), donc si vous voulez transformer un peut-être-statique en un statique réel plus tard (lorsque vous avez besoin de ses fonctionnalités en dehors d'une instance), vous pouvez. Cependant, le refactoring inverse, transformant un peut-être-statique en une méthode d'instance est BEAUCOUP plus cher.

Avec de grandes bases de code, il est préférable d'errer du côté de la facilité d'extension, plutôt que du côté de la pureté généalogique.

Donc, pour les grands projets, ne rendez pas les choses statiques, sauf si vous en avez besoin. Pour les petits projets, faites ce que vous préférez.

59
Scott Wisniewski

Je voudrais pas en faire un public membre statique de cette classe. La raison en est que le rendre public statique signifie quelque chose sur le type de la classe: non seulement que "ce type sait comment faire ce comportement", mais aussi "il est de la responsabilité de ce type d'exécuter ce comportement". Et les chances sont que le comportement n'a plus de véritable relation avec le type plus grand.

Cela ne signifie pas pour autant que je ne le rendrais pas statique du tout. Demandez-vous ceci: la nouvelle méthode pourrait-elle logiquement appartenir ailleurs? Si vous pouvez répondre "oui" à cela, vous voulez probablement le rendre statique (et le déplacer également). Même si ce n'est pas vrai, vous pouvez toujours le rendre statique. Il suffit de ne pas le marquer public.

Par souci de commodité, vous pouvez au moins le marquer internal. Cela évite généralement d'avoir à déplacer la méthode si vous n'avez pas facilement accès à un type plus approprié, mais la laisse toujours accessible là où c'est nécessaire de manière à ce qu'elle n'apparaisse pas dans l'interface publique pour les utilisateurs de votre classe. .

43
Joel Coehoorn

Pas nécessairement.

Le passage de méthodes publiques de statiques à non statiques est un changement de rupture et nécessiterait des modifications pour tous vos appelants ou consommateurs. Si une méthode semble être une méthode d'instance, mais qu'il se trouve qu'elle n'utilise aucun membre d'instance, je suggère d'en faire une méthode d'instance comme mesure de pérennisation.

20
Michael

Oui. La raison pour laquelle "il peut être statique" est qu'il n'opère pas sur l'état de l'objet sur lequel il est appelé. Ce n'est donc pas une méthode d'instance, mais une méthode de classe. S'il peut faire ce qu'il doit faire sans jamais accéder aux données de l'instance, il doit être statique.

13
JP Alioto

Oui, ça devrait. Il existe diverses mesures de couplage qui mesurent la façon dont votre classe dépend d'autres choses, comme d'autres classes, méthodes, etc. Rendre les méthodes statiques est un moyen de réduire le degré de couplage, car vous pouvez être sûr une méthode statique ne fait référence à aucun membre.

12
Jabe

Je pense que cela le rendrait un peu plus lisible si vous le marquiez comme statique ... Ensuite, quelqu'un qui viendrait saurait qu'il ne fait référence à aucune variable d'instance sans avoir à lire la fonction entière ...

8
Jason Punyon

Les méthodes statiques sont plus rapides que les méthodes non statiques, donc oui, elles devraient être statiques si elles le peuvent et il n'y a aucune raison particulière de les laisser non statiques.

6
agnieszka

Personnellement, je suis un grand fan d'apatridie. Votre méthode a-t-elle besoin d'accéder à l'état de la classe? Si la réponse est non (et probablement non, sinon vous n'envisageriez pas d'en faire une méthode statique), alors oui, allez-y.

Aucun accès à l'État n'est moins un casse-tête. Tout comme c'est une bonne idée de cacher les membres privés qui ne sont pas nécessaires aux autres classes, c'est une bonne idée de cacher l'état aux membres qui n'en ont pas besoin. Un accès réduit peut signifier moins de bugs. De plus, cela facilite le filetage car il est beaucoup plus facile de garder les membres statiques en sécurité. Il y a également une considération de performance car le runtime n'a pas besoin de passer une référence à this comme paramètre pour les méthodes statiques.

Bien sûr, l'inconvénient est que si vous trouvez que votre méthode précédemment statique devra accéder à l'état pour une raison quelconque, vous devez le changer. Maintenant, je comprends que cela peut être un problème pour les API publiques, donc s'il s'agit d'une méthode publique dans une classe publique, alors vous devriez peut-être réfléchir un peu aux implications de cela. Pourtant, je n'ai jamais fait face à une situation dans le monde réel où cela a réellement causé un problème, mais peut-être que j'ai juste de la chance.

Alors oui, allez-y, par tous les moyens.

6
Tamas Czinege

Je suis surpris que si peu mentionnent en fait l'encapsulation ici. Une méthode d'instance aura automatiquement accès à tous les champs, propriétés et méthodes privés (instance). En plus de toutes celles protégées héritées des classes de base.

Lorsque vous écrivez du code, vous devez l'écrire de manière à en exposer le moins possible et également à y accéder le moins possible.

Alors oui, il pourrait être important de rendre votre code rapide, ce qui se produirait si vous rendiez vos méthodes statiques, mais généralement plus important, c'est de rendre votre code aussi incapable de créer des bogues que possible. Une façon d'y parvenir est de faire en sorte que votre code ait accès le moins possible à des "trucs privés".

Cela peut sembler hors de propos à première vue car l'OP parle évidemment de refactoring qui ne peut pas mal se passer dans ce scénario et créer de nouveaux bugs, cependant ce code refactoré doit être maintenu à l'avenir et modifié ce qui fait que votre code a une plus grande "attaque" surface "en ce qui concerne les nouveaux bogues s'il a accès à des membres d'instance privés. Donc, en général, je pense que la conclusion ici est que "oui, la plupart du temps, vos méthodes devraient être statiques" sauf s'il y a d'autres raisons de ne pas les avoir statiques. Et cela simplement parce que c'est "une meilleure utilisation de l'encapsulation et du masquage des données et crée un code" plus sûr "" ...

5
Thomas Hansen

Faire quelque chose de statique simplement parce que vous le pouvez n'est pas une bonne idée. Les méthodes statiques doivent être statiques en raison de leur conception, et non pas par hasard.

Comme Michael l'a dit, le modifier plus tard cassera le code qui l'utilise.

Cela dit, il semble que vous créez une fonction utilitaire privée pour la classe qui est, en fait, statique par conception.

4
17 of 26

Si vous avez pu refactoriser quelques lignes et que la méthode résultante peut être statique, cela indique probablement que les lignes que vous avez retirées de cette méthode n'appartiennent pas du tout à la classe conteneur, et vous devriez envisager de les déplacer vers leur propre classe.

4
Chris Shaffer

Personnellement, je n'aurais pas d'autre choix que de le rendre statique. Resharper émet un avertissement dans ce cas et notre PM a une règle "Aucun avertissement du Resharper".

2
Prankster

Je transformerais certainement tout ce que je peux en statique pour une raison différente:

Les fonctions statiques, lorsqu'elles sont JIT, sont appelées sans paramètre "this". Cela signifie, par exemple, qu'une fonction non statique à 3 paramètres (méthode membre) est poussée avec 4 paramètres sur la pile.

La même fonction compilée comme une fonction statique serait appelée avec 3 paramètres. Cela peut libérer des registres pour le JIT et économiser de l'espace de pile ...

1
damageboy

Vous devriez penser à vos méthodes et classes:

  • Comment allez-vous les utiliser?
  • Avez-vous besoin de beaucoup d'accès à eux à différents niveaux de votre code?
  • Est-ce une méthode/classe que je peux utiliser dans presque tous les projets imaginables.

Si les deux derniers sont "oui", alors votre méthode/classe devrait probablement être statique.

L'exemple le plus utilisé est probablement la classe Math. Chaque langue principale OO l'a et toutes les méthodes sont statiques. Parce que vous devez pouvoir les utiliser n'importe où, n'importe quand, sans créer d'instance).

Un autre bon exemple est la méthode Reverse() en C #.
Il s'agit d'une méthode statique dans la classe Array. Il inverse l'ordre de votre tableau.

Code:

public static void Reverse(Array array)

Il ne retourne même rien, votre tableau est inversé, car tous les tableaux sont des instances de la classe Array.

1
KdgDev

Tant que vous créez la nouvelle méthode private static ce n'est pas un changement de rupture. En fait, FxCop inclut ces conseils comme l'une de ses règles ( http://msdn.Microsoft.com/en-us/library/ms245046 (VS.80) .aspx ), avec les informations suivantes :

Après avoir marqué les méthodes comme statiques, le compilateur émettra des sites d'appels non virtuels à ces membres. L'émission de sites d'appels non virtuels empêchera une vérification au moment de l'exécution pour chaque appel qui garantit que le pointeur d'objet actuel n'est pas nul. Cela peut entraîner un gain de performances mesurable pour le code sensible aux performances. Dans certains cas, l'échec de l'accès à l'instance d'objet actuelle représente un problème de correction.

Cela étant dit, le premier commentaire de David Kean résume plus succinctement les préoccupations en disant qu'il s'agit en fait plus d'être correct que de gagner en performances:

Bien que cette règle soit classée comme un problème de performances, l'amélioration des performances de rendre une méthode statique n'est que d'environ 1%. Il s'agit plutôt d'un problème d'exactitude qui pourrait indiquer un membre incomplet ou un bogue dans le membre par son échec à utiliser d'autres membres d'instance. Le marquage d'une méthode statique ( Shared dans Visual Basic) indique clairement son intention de ne pas toucher à l'état d'instance.

1
Scott Dorman

Je suis dans le camp "rendre les méthodes privées statiques". La création d'une méthode publique peut introduire un couplage dont vous ne voulez pas et peut réduire la testabilité: vous ne pouvez pas bloquer une méthode statique publique.

Si vous souhaitez tester de manière unitaire une méthode qui utilise une méthode statique publique, vous finissez également par tester la méthode statique, ce qui n'est peut-être pas ce que vous voulez.

1
Lennaert

Cela dépend mais généralement je ne rend pas ces méthodes statiques. Le code est en constante évolution et peut-être qu'un jour je voudrai rendre cette fonction virtuelle et la remplacer dans une sous-classe. Ou peut-être qu'un jour, il devra référencer des variables d'instance. Il sera plus difficile d'effectuer ces changements si chaque site d'appel doit être changé.

1
Brian Ensink

Je suggère que la meilleure façon d'y penser est la suivante: si vous avez besoin d'une méthode de classe qui doit être appelée lorsqu'aucune instance de la classe n'est instanciée, ou qui maintient une sorte d'état global, alors statique est une bonne idée. Mais en général, je suggère que vous préfériez rendre les membres non statiques.

1
Foredecker

Les méthodes intrinsèquement statiques qui, pour une raison quelconque, sont rendues non statiques sont simplement ennuyeuses. En être témoin:

J'appelle ma banque et demande mon solde.
Ils demandent mon numéro de compte.
C'est suffisant. Méthode d'instance.

J'appelle ma banque et lui demande son adresse postale.
Ils demandent mon numéro de compte.
WTF? Échec - aurait dû être une méthode statique.

1
I. J. Kennedy

Je le regarde généralement dans une perspective fonctionnelle de fonctions pures. Doit-il s'agir d'une méthode d'instance? Sinon, vous pouvez bénéficier de forcer l'utilisateur à transmettre les variables et de ne pas modifier l'état de l'instance actuelle. (Eh bien, vous pouvez toujours modifier l'état, mais le fait est, par conception, de ne pas le faire.) Je conçois généralement des méthodes d'instance en tant que membres publics et fais de mon mieux pour rendre les membres privés statiques. Si nécessaire (vous pourrez ensuite les extraire plus facilement dans d'autres classes plus tard.

0
user29439