Les méthodes C # qui * peuvent * être statiques devraient-elles être statiques? [fermé]


103

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

Nous en discutions aujourd'hui et je suis en quelque sorte sur la clôture. Imaginez que vous ayez une longue méthode dont vous refactorisez quelques lignes. La nouvelle méthode prend probablement quelques variables locales de la méthode parente et renvoie une valeur. Cela signifie que cela pourrait être statique.

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


1
Copie

41
"assez exact" est un oxymore
Matt Briggs

1
Resharper , l'outil d'outils Visual Studio, dit oui! :-)
Rebecca

@Junto Peut-être dans votre version, mais la mienne dit que cela peut être rendu statique ...
Robbie Dee

Réponses:


59

Ça dépend. Il existe vraiment 2 types de méthodes statiques:

  1. Des méthodes statiques parce qu'elles PEUVENT
  2. Méthodes qui sont statiques parce qu'elles DOIVENT l'être

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

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

Dans une grande base de code, cependant, le grand nombre de sites d'appels 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 fasse ce dont j'ai besoin".

Cela peut entraîner soit:

  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 de plus de 200K LOC, je ne rendrais les méthodes statiques que si ce sont des méthodes incontournables.

La refactorisation de non-statique à statique est relativement facile (ajoutez simplement un mot-clé), donc si vous voulez transformer un can-be-static en une véritable statique plus tard (lorsque vous avez besoin de ses fonctionnalités en dehors d'une instance), vous pouvez le faire. Cependant, le refactoring inverse, transformer un can-be-static en une méthode d'instance est BEAUCOUP plus cher.

Avec de grandes bases de code, il vaut mieux se tromper du côté de la facilité d'extension, plutôt que du côté de la pureté idéologique.

Donc, pour les grands projets, ne rendez pas les choses statiques à moins que vous n'en ayez besoin. Pour les petits projets, faites ce que vous préférez.


43

Je n'en ferais pas un membre statique public de cette classe . La raison en est que le rendre public statique, c'est dire 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 il y a de fortes chances que le comportement n'ait plus de relation réelle avec le type plus large.

Cela ne veut pas dire que je ne le rendrais pas du tout statique. Posez-vous la question suivante: la nouvelle méthode pourrait-elle logiquement appartenir ailleurs? Si vous pouvez répondre "oui" à cela, vous voudrez probablement le rendre statique (et le déplacer également). Même si ce n'est pas vrai, vous pouvez toujours le rendre statique. Ne le marquez pas public.

Pour des raisons de commodité, vous pouvez au moins le marquer internal. Cela évite généralement de devoir déplacer la méthode si vous n'avez pas un accès facile à 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 aux utilisateurs de votre classe .


6
D'accord. Je fais généralement la méthode "statique privée" dans un cas comme celui-ci.
harpo

6
Je ne présumerais pas non plus de statique privée. L'essentiel est de vous demander: cette méthode s'inscrit-elle logiquement dans ce type ou est-elle juste ici pour des raisons de commodité? Dans ce dernier cas, pourrait-il mieux convenir ailleurs?
Joel Coehoorn

1
Comme: "la nouvelle méthode pourrait-elle logiquement appartenir ailleurs" - l'indice est-elle qu'elle ne dépend pas de l'état local, peut-être que le type de retour est là où il appartient?
AndyM

20

Pas nécessairement.

Le déplacement des méthodes publiques de statiques vers non statiques est un changement radical et nécessiterait des changements pour tous vos appelants ou consommateurs. Si une méthode ressemble à une méthode d'instance, mais qu'elle n'utilise aucun membre d'instance, je suggérerais d'en faire une méthode d'instance comme mesure de pérennité.


Je pense qu'il fait principalement référence aux méthodes privées
George Mauer

@Ray - C'est vrai, cela ne s'applique qu'aux membres non privés. J'ai mis à jour ma réponse pour refléter cela.
Michael

Mes pensées exactement - ce n'est pas parce que vous pourriez faire quelque chose de statique que vous devez ou devriez .....
marc_s

Alors, que feriez-vous pour les méthodes privées qui pourraient être rendues statiques?
Ray

@Ray - Probablement laisser tel quel jusqu'à ce que j'aie une raison suffisante de passer à la statique.
Michael

13

Oui. La raison "elle peut être statique" est qu'elle n'opère pas sur l'état de l'objet sur lequel elle est appelée. 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, alors il doit être statique.


11

Oui, ça devrait. Il existe différentes mesures de couplage qui mesure la façon dont votre classe dépend d'autres choses, comme les autres classes, méthodes, etc. Faire statique des méthodes est un moyen de maintenir le degré de couplage vers le bas, puisque vous pouvez être sûr d' une méthode statique ne fait référence à aucune membres.


7
Pas nécessairement. Une méthode statique n'accédera pas aux informations d'instance, pas de membres, comme vous l'avez dit, mais elle est capable d'interagir avec d'autres classes ainsi qu'avec une autre méthode courante. Être statique ne signifie pas nécessairement que le couplage est réduit. Cependant, j'ai compris votre point.
Victor Rodrigues

Au lieu de cela, la statique augmente le couplage, car vous êtes limité exactement à cette méthode statique, aucun moyen de l'errer par exemple et donc aucun moyen de changer le comportement.
HimBromBeere

8

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 ...


6

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

Aucun accès à l'état, c'est moins de maux de tête. Tout comme c'est une bonne idée de masquer les membres privés qui ne sont pas nécessaires par d'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 bogues. En outre, cela facilite le threading car il est beaucoup plus facile de garder les membres statiques thread-safe. Il y a également une considération pour les performances car le runtime n'a pas besoin de passer une référence à cela en tant que paramètre pour les méthodes statiques.

Bien sûr, l'inconvénient est que si jamais vous constatez 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, vous devriez peut-être réfléchir un peu aux implications de cela. Pourtant, je n'ai jamais été confronté à une situation dans le monde réel où cela posait un problème, mais peut-être que j'ai juste de la chance.

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


1
Une méthode statique peut toujours avoir accès à state. Il obtient simplement l'état de l'objet qui lui est passé. Inversement, les champs d'instance ne contiennent pas nécessairement un état mutable.
Jørgen Fogh

6

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 .


3
C'est techniquement vrai, mais pas dans un sens matériel réel. La différence entre statique / non sera très, très rarement un facteur de performance.
Foredecker

22
-1: Optimisation prématurée des manuels. La vitesse ne devrait certainement pas être le premier critère pour décider du statique par rapport au non statique dans le cas général.
Incertain

2
D'accord avec Pas sûr, cela devrait être votre dernière raison de considérer la statique ou non.
Samuel

5
Mon point est que la vitesse est l'une des pires raisons que vous puissiez avoir pour décider si une fonction est statique ou non statique dans 99% des cas. Il y a des considérations beaucoup plus importantes en ce qui concerne la conception OO que d'autres articles développent.
Incertain

2
@agnieszka: La raison particulière d'utiliser généralement des méthodes d'instance au lieu de méthodes statiques est l'état. Si vous laissez vos méthodes statiques, dans une application complexe vous introduirez des bugs qui vous feront arracher les cheveux. Pensez à modifier l'état global, les conditions de course, la sécurité des threads, etc.
Sandor Davidhazi

5

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

Lorsque vous écrivez du code, vous devez l'écrire de manière à exposer le moins possible et aussi à avoir accès au moins possible.

Donc, oui, il peut ê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 d'avoir accès à votre code le moins possible de "trucs privés".

Cela peut paraître hors de propos à première vue puisque l'OP parle évidemment de refactoring qui ne peut pas se tromper dans ce scénario et créer de nouveaux bugs, cependant ce code refactorisé doit être maintenu dans le futur et modifié ce qui fait que votre code a une attaque plus " surface "en ce qui concerne les nouveaux bogues s'il a accès aux membres de l'instance privée. Donc, en général, je pense que la conclusion ici est que "oui, la plupart de vos méthodes devraient être statiques" à moins qu'il n'y ait 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 "" ...


4

Rendre 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 par hasard.

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

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


4

Si vous avez pu refactoriser quelques lignes et que la méthode résultante pourrait être statique, c'est probablement une indication que les lignes que vous avez extraites de cette méthode n'appartiennent pas du tout à la classe contenant, et vous devriez envisager de les déplacer dans leur propre classe.


2

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".


1
Vous pouvez modifier vos paramètres ReSharper: P
Bernhard Hofmann

1
Si c'était si facile, nous n'avions aucune usure du Resharper ... jamais :)
Prankster

1

Cela dépend mais en général je ne rend pas ces méthodes statiques. Le code est toujours en train de changer et peut-être qu'un jour je voudrais 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 de faire ces changements si chaque site d'appel doit être changé.


Ouais, mais si un jour vous devez faire cela, vous pouvez toujours faire en sorte que ce ne soit pas statique. Ou est-ce que je manque quelque chose?
Ray

1
@Ray - Je couvre cela dans ma réponse. statique à non statique est un changement radical, donc tous les consommateurs doivent être modifiés. Ce n'est pas un gros problème pour un petit programme, mais s'il s'agit d'une bibliothèque destinée à être consommée par d'autres, cela doit être pris en compte.
Michael

Tous les sites d'appel doivent passer d'un appel de méthode statique à un appel de fonction membre.
Brian Ensink

Désolé, vous l'avez ajouté après mon commentaire. Dans mon esprit, je pensais aux méthodes privées, mais c'est un point valable pour les méthodes publiques.
Ray

... ou un jour, vous pouvez le jeter. ces arguments ne sont pas assez bons pour que je rende une méthode non statique.
agnieszka

1

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 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

Vous devriez penser à vos méthodes et classes:

  • Comment allez-vous les utiliser?
  • Avez-vous besoin de beaucoup d'accès à partir de 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 Mathclasse. Chaque langage OO majeur 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 Reverse()méthode en C #.
Il s'agit d'une méthode statique de la Arrayclasse. Il inverse l'ordre de votre tableau.

Code:

public static void Reverse(Array array)

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


Le Math est un mauvais exemple. Je suppose que c'est mieux: newnumber = number.round (2) que newnumber = Math.round (number)
graffic

3
La classe Math est l'exemple parfait de l'utilisation de classes statiques. C'est le sujet de ce sujet, pas la façon dont vous préférez arrondir les nombres ...
KdgDev

1

Tant que vous rendez la nouvelle méthode privée statique, ce n'est pas un changement radical. 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:

Une fois que vous avez 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 est non nul. Cela peut entraîner un gain de performances mesurable pour le code sensible aux performances. Dans certains cas, l'incapacité d'accéder à l'instance d'objet actuelle représente un problème d'exactitude.

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 performance:

Bien que cette règle soit classée comme un problème de performances, l'amélioration des performances en rendant 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 bogue incomplet ou un bogue dans le membre en raison de son incapacité à utiliser d'autres membres d'instance. Le marquage d'une méthode statique ( Shared en Visual Basic) indique clairement son intention de ne pas toucher l'état de l'instance.


1

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 en tant que fonction statique serait appelée avec 3 paramètres. Cela peut libérer des registres pour le JIT et économiser de l'espace dans la pile ...


1

Je suis dans le camp "uniquement 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 diminuer la testabilité: vous ne pouvez pas stuber une méthode statique publique.

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


1

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

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

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


1
Et si différents clients sont servis par différentes succursales? La correspondance postale au bureau principal de la banque peut éventuellement la faire parvenir à la succursale appropriée, mais cela ne signifie pas qu'un client ne serait pas mieux servi en utilisant l'adresse de la succursale qui le dessert.
supercat

0

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


-1

Dans ces cas, j'ai tendance à déplacer la méthode vers une bibliothèque statique ou utils, donc je ne mélange pas le concept d '"objet" avec le concept de "classe"

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.