web-dev-qa-db-fra.com

Quand utiliser des classes statiques en C #

Voici ce que MSDN doit dire sous Quand utiliser des classes statiques :

static class CompanyInfo
{
    public static string GetCompanyName() { return "CompanyName"; }
    public static string GetCompanyAddress() { return "CompanyAddress"; }
    //...
}

Utilisez une classe statique comme unité d'organisation pour les méthodes non associées à des objets particuliers. De plus, une classe statique peut rendre votre implémentation plus simple et plus rapide, car vous n'avez pas besoin de créer un objet pour appeler ses méthodes. Il est utile d'organiser les méthodes à l'intérieur de la classe de manière significative, telles que les méthodes de la classe Math dans l'espace de noms System.

Pour moi, cet exemple ne semble pas couvrir de très nombreux scénarios d'utilisation possibles pour les classes statiques. Dans le passé, j'ai utilisé des classes statiques pour des suites sans état de fonctions connexes, mais c'est à peu près tout. Alors, dans quelles circonstances une classe devrait (et ne devrait pas) être déclarée statique?

591
pbh101

J'ai écrit mes pensées sur les classes statiques dans une réponse antérieure Stack Overflow: Classe avec une seule méthode - meilleure approche?

J'aimais les classes utilitaires remplies de méthodes statiques. Ils ont procédé à une excellente consolidation des méthodes d'assistance qui, autrement, auraient été générées, entraînant redondance et maintenance. Ils sont très faciles à utiliser, aucune instanciation, aucune élimination, rien que du feu. J'imagine que c'était ma première tentative involontaire de créer une architecture orientée service - de nombreux services sans état qui faisaient simplement leur travail et rien d'autre. Cependant, à mesure que le système se développe, les dragons arrivent.

Polymorphisme

Disons que nous avons la méthode UtilityClass.SomeMethod qui bourdonne joyeusement. Tout à coup, nous devons modifier légèrement les fonctionnalités. La plupart des fonctionnalités sont les mêmes, mais nous devons néanmoins modifier quelques éléments. Si cela n’avait pas été une méthode statique, nous pourrions créer une classe de dérivés et modifier le contenu de la méthode selon les besoins. Comme c'est une méthode statique, nous ne pouvons pas. Bien sûr, si nous devons simplement ajouter des fonctionnalités avant ou après l’ancienne méthode, nous pouvons créer une nouvelle classe et appeler l’ancienne à l’intérieur de celle-ci - mais c’est tout simplement dégoûtant.

Problèmes d'interface

Les méthodes statiques ne peuvent pas être définies via des interfaces pour des raisons logiques. Et comme nous ne pouvons pas redéfinir les méthodes statiques, les classes statiques sont inutiles lorsque nous devons les transmettre par leur interface. Cela nous rend incapables d'utiliser des classes statiques dans le cadre d'un modèle de stratégie. Nous pourrions corriger quelques problèmes en en passant des délégués à la place des interfaces .

Test

Cela va fondamentalement de pair avec les problèmes d’interface mentionnés ci-dessus. Notre capacité d'interchanger les implémentations étant très limitée, nous aurons également du mal à remplacer le code de production par le code de test. Encore une fois, nous pouvons les résumer, mais cela nous obligera à modifier de grandes parties de notre code simplement pour pouvoir accepter les wrappers à la place des objets réels.

Crée des blobs

Comme les méthodes statiques sont généralement utilisées en tant qu'utilitaires et que leurs méthodes ont des objectifs différents, nous allons rapidement nous retrouver avec une classe volumineuse remplie de fonctionnalités non cohérentes. Idéalement, chaque classe doit avoir un objectif unique au sein du système. Je préférerais de beaucoup avoir cinq fois les classes tant que leurs objectifs sont bien définis.

Paramètre de fluage

Pour commencer, cette petite méthode statique mignonne et innocente peut prendre un seul paramètre. À mesure que la fonctionnalité augmente, deux nouveaux paramètres sont ajoutés. Bientôt d'autres paramètres, facultatifs, sont ajoutés. Nous créons donc des surcharges de la méthode (ou ajoutons simplement des valeurs par défaut, dans les langues qui les prennent en charge). D'ici peu, nous avons une méthode qui prend 10 paramètres. Seuls les trois premiers sont vraiment nécessaires, les paramètres 4 à 7 sont facultatifs. Mais si le paramètre 6 est spécifié, vous devez également renseigner 7-9 ... Si nous avions créé une classe dans le seul but de faire ce que cette méthode statique a fait, nous pourrions résoudre ce problème en prenant les paramètres requis dans le fichier. constructeur, et en permettant à l'utilisateur de définir des valeurs facultatives via des propriétés ou des méthodes permettant de définir plusieurs valeurs interdépendantes en même temps. En outre, si une méthode présente une telle complexité, elle doit de toute façon être dans sa propre classe.

Demander aux consommateurs de créer une instance de classes sans raison

L'un des arguments les plus courants est le suivant: pourquoi demander aux consommateurs de notre classe de créer une instance pour invoquer cette méthode unique, tout en ne l'utilisant pas par la suite? Créer une instance d'une classe est une opération très très économique dans la plupart des langues, la rapidité n'est donc pas un problème. L'ajout d'une ligne de code supplémentaire au consommateur représente un faible coût pour poser les bases d'une solution beaucoup plus facile à gérer dans le futur. Enfin, si vous souhaitez éviter de créer des instances, créez simplement un wrapper singleton de votre classe qui permette une réutilisation facile - bien que cela rende l'exigence que votre classe soit sans état. Si ce n'est pas sans état, vous pouvez toujours créer des méthodes de wrapper statiques qui gèrent tout, tout en vous offrant tous les avantages à long terme. Enfin, vous pouvez également créer une classe qui masque l'instanciation comme s'il s'agissait d'un singleton: MyWrapper.Instance est une propriété qui renvoie simplement new MyClass();.

Seul un Sith traite en absolu

Bien sûr, il y a des exceptions à mon aversion pour les méthodes statiques. Les vraies classes d'utilitaires qui ne posent aucun risque de gonflement constituent d'excellents cas pour les méthodes statiques - System.Convert par exemple. Si votre projet est unique et ne nécessite aucune maintenance future, l'architecture globale n'est pas très importante - statique ou non statique, peu importe - la vitesse de développement l'est toutefois.

Normes, normes, normes!

L'utilisation de méthodes d'instance ne vous empêche pas d'utiliser également des méthodes statiques, et inversement. Tant que la différenciation est raisonnée et normalisée. Il n'y a rien de pire que de regarder une couche métier contenant différentes méthodes d'implémentation.

711
Mark S. Rasmussen

Lorsque vous décidez de rendre une classe statique ou non statique, vous devez examiner les informations que vous essayez de représenter. Cela implique un style de programmation plus 'bottom-up', dans lequel vous vous concentrez sur les données que vous représentez en premier. La classe que vous écrivez est-elle un objet du monde réel, comme un rocher ou une chaise? Ces objets sont physiques et ont des attributs physiques tels que la couleur, le poids qui vous indique que vous souhaitez peut-être instancier plusieurs objets ayant des propriétés différentes. Je veux peut-être une chaise noire ET une chaise rouge en même temps. Si vous avez besoin de deux configurations en même temps, vous savez immédiatement que vous souhaitez l’instancier en tant qu’objet afin que chaque objet puisse être unique et exister en même temps.

De l'autre côté, les fonctions statiques ont tendance à se prêter davantage aux actions qui n'appartiennent pas à un objet du monde réel ou à un objet que vous pouvez facilement représenter. Rappelez-vous que les prédécesseurs de C # sont C++ et C où vous pouvez simplement définir des fonctions globales qui n'existent pas dans une classe. Cela prête plus à la programmation 'top-down'. Les méthodes statiques peuvent être utilisées dans les cas où il n'est pas logique qu'un "objet" exécute la tâche. En vous obligeant à utiliser des classes, cela facilite simplement le regroupement des fonctionnalités associées, ce qui vous permet de créer un code plus facilement maintenable.

La plupart des classes peuvent être représentées de manière statique ou non statique, mais lorsque vous avez un doute, retournez à vos racines OOP et essayez de réfléchir à ce que vous représentez. Est-ce un objet qui exécute une action (une voiture qui peut accélérer, ralentir, tourner) ou quelque chose de plus abstrait (comme l'affichage d'une sortie)?.

Entrez en contact avec votre OOP intérieure et vous ne pourrez jamais vous tromper!

144
Despertar

Pour C # 3.0, les méthodes d'extension ne peuvent exister que dans les classes statiques de niveau supérieur.

35
Mark Cidade

Si vous utilisez des outils d'analyse de code (par exemple, FxCop ), il est recommandé de marquer une méthode static si celle-ci n'accède pas aux données d'instance. La raison en est qu'il y a un gain de performance. MSDN: CA1822 - Marquer les membres comme statiques .

C'est plus une ligne directrice qu'une règle, vraiment ...

22
user25306

J'ai tendance à utiliser des classes statiques pour les usines. Par exemple, il s'agit de la classe de journalisation dans l'un de mes projets:

public static class Log
{
   private static readonly ILoggerFactory _loggerFactory =
      IoC.Resolve<ILoggerFactory>();

   public static ILogger For<T>(T instance)
   {
      return For(typeof(T));
   }

   public static ILogger For(Type type)
   {
      return _loggerFactory.GetLoggerFor(type);
   }
}

Vous avez peut-être même remarqué qu'IoC est appelé avec un accesseur statique. La plupart du temps pour moi, si vous pouvez appeler des méthodes statiques sur une classe, c'est tout ce que vous pouvez faire, alors je marque la classe comme statique pour plus de clarté.

12
Rob

Les classes statiques sont très utiles et ont une place, par exemple les bibliothèques.

Le meilleur exemple que je puisse donner est la classe .Net Math, une classe statique System namespace qui contient une bibliothèque de fonctions mathématiques.

C'est comme n'importe quoi d'autre, utilisez le bon outil pour le travail, sinon vous pouvez en abuser.

Ignorer carrément les classes statiques comme étant fausses, ne les utilisez pas, ou dire "il ne peut y en avoir qu'une seule" ou aucune, est aussi erroné que de les utiliser.

C # .Net contient un certain nombre de classes statiques qui sont utilisées comme la classe Math.

Donc, étant donné la mise en œuvre correcte, ils sont extrêmement utiles.

Nous avons une classe TimeZone statique qui contient un certain nombre de fonctions de fuseau horaire liées aux entreprises. Il n'est donc pas nécessaire de créer plusieurs instances de la classe, tout comme la classe Math. Elle contient un ensemble de fonctions réalistes TimeZone accessibles dans une classe statique. .

10
Don

J'ai commencé à utiliser des classes statiques lorsque je souhaitais utiliser des fonctions plutôt que des classes comme unité de réutilisation. Auparavant, je parlais du mal des classes statiques. Cependant, l'apprentissage F # m'a fait voir les choses sous un nouveau jour.

Qu'est-ce que je veux dire par là? Eh bien, disons que lorsque je travaille sur du code super DRY , je me retrouve avec un tas de classes à une méthode. Je peux simplement extraire ces méthodes dans une classe statique, puis les injecter dans des dépendances à l'aide d'un délégué. Cela joue également bien avec mon injection de dépendance (DI) conteneur de choix Autofac.

Bien sûr, prendre une dépendance directe sur une méthode statique est toujours généralement diabolique (il existe des utilisations non perverses).

10
bentayloruk

J'utilise des classes statiques comme moyen de définir une "fonctionnalité supplémentaire" qu'un objet d'un type donné pourrait utiliser dans un contexte spécifique. Habituellement, il s’agit de classes d’utilité.

En dehors de cela, je pense que "Utiliser une classe statique comme unité d'organisation pour les méthodes non associées à des objets particuliers". décrivent assez bien leur utilisation prévue.

9
Trap

C’est une autre question ancienne mais très chaude depuis que OOP est entré en jeu. Il existe de nombreuses raisons d’utiliser (ou non) une classe statique, bien sûr, et la plupart d’entre elles ont été couvertes dans une multitude de réponses.

Je vais juste ajouter mes 2 centimes à ceci, en disant que je fais une classe statique, quand cette classe est quelque chose qui serait unique dans le système et que cela n’aurait aucun sens de faire en sorte qu’il en soit ainsi dans le programme. Cependant, je réserve cette utilisation pour les grandes classes. Je ne déclare jamais les classes aussi petites que dans l'exemple MSDN comme "statiques" et, certainement, pas les classes qui vont être membres d'autres classes.

J'aime aussi noter que static méthodes et static classes sont deux choses différentes à considérer. Les principaux inconvénients mentionnés dans la réponse acceptée concernent statiques méthodes. static classes offre la même flexibilité que les classes normales (en ce qui concerne les propriétés et les paramètres) et toutes les méthodes utilisées doivent être pertinentes pour la finalité de l'existence de la classe.

À mon avis, un bon exemple de candidat pour une classe statique est une classe "FileProcessing", qui contiendrait toutes les méthodes et propriétés pertinentes pour les différents objets du programme permettant d'effectuer des opérations FileProcessing complexes. Avoir plus d'une instance de cette classe n'a guère de sens et être statique la rendra facilement accessible à tout le contenu de votre programme.

7
ThunderGr

Je n'utilise que des classes statiques pour les méthodes d'assistance, mais avec l'avènement de C # 3.0, je préférerais utiliser des méthodes d'extension pour celles-ci.

J'utilise rarement des méthodes de classes statiques pour les mêmes raisons que celles du singleton "design pattern".

2
jonnii

Basé sur MSDN :

  1. Vous ne pouvez pas créer l'instance pour les classes statiques
  2. Si la classe est déclarée statique, la variable membre doit être statique pour cette classe.
  3. Scellé [Ne peut être hérité]
  4. Ne peut pas contenir le constructeur d'instance
  5. Gestion de la mémoire

Exemple: les calculs mathématiques (valeurs mathématiques) ne changent pas [CALCUL STANDARD POUR LES VALEURS DÉFINIES]

1
Vicky