Question Quand utiliser des classes statiques en C # [en double]


Cette question a déjà une réponse ici:

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"; }
    //...
}

Utiliser une classe statique en tant qu'unité de   organisation pour les méthodes non   associé à des objets particuliers.   En outre, une classe statique peut faire votre   implémentation plus simple et plus rapide   parce que vous n'avez pas besoin de créer   objet afin d'appeler ses méthodes.   Il est utile d'organiser les méthodes   à l'intérieur de la classe d'une manière significative,   tels 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 rapport de fonctions connexes, mais c'est à peu près tout. Alors, dans quelles circonstances (et ne devrait-on pas) qu'une classe soit déclarée statique?


534
2017-10-27 20:53


origine


Réponses:


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

J'avais l'habitude d'aimer les classes d'utilité remplies de méthodes statiques. Ils ont fait une grande consolidation des méthodes auxiliaires qui, autrement, seraient à l'origine de la redondance et de l'enfer de la maintenance. Ils sont très faciles à utiliser, pas d'instanciation, pas d'élimination, juste fire'n'forget. Je suppose que c'était ma première tentative inconsciente de créer une architecture orientée services - beaucoup de services sans état qui ont juste fait leur travail et rien d'autre. À mesure qu'un système se développe, les dragons arrivent.

Polymorphisme

Disons que nous avons la méthode UtilityClass.SomeMethod qui bourdonne heureusement le long. Soudainement nous devons changer la fonctionnalité légèrement. La plupart des fonctionnalités sont les mêmes, mais nous devons néanmoins changer quelques parties. S'il n'avait pas été une méthode statique, nous pourrions faire une classe dérivée et changer le contenu de la méthode si nécessaire. Comme c'est une méthode statique, nous ne pouvons pas. Bien sûr, si nous avons juste besoin d'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 - mais c'est juste grossier.

Problèmes d'interface

Les méthodes statiques ne peuvent pas être définies via des interfaces pour des raisons logiques. Et puisque nous ne pouvons pas remplacer les méthodes statiques, les classes statiques sont inutiles quand nous avons besoin de les passer par leur interface. Cela nous rend incapable d'utiliser des classes statiques dans le cadre d'un modèle de stratégie. Nous pourrions corriger certains problèmes en passer des délégués au lieu d'interfaces.

Essai

Cela va essentiellement de pair avec les problèmes d'interface mentionnés ci-dessus. Comme notre capacité d'interchanger des implémentations est très limitée, nous aurons aussi du mal à remplacer le code de production par du code de test. Encore une fois, nous pouvons les emballer, mais cela nous obligera à changer de grandes parties de notre code juste pour pouvoir accepter les wrappers au lieu des objets réels.

Fosters blobs

Comme les méthodes statiques sont généralement utilisées en tant que méthodes utilitaires et que les méthodes utilitaires ont généralement des finalités différentes, nous finirons rapidement par une grande classe remplie de fonctionnalités non cohérentes - idéalement, chaque classe devrait avoir un seul but dans le système. Je préférerais avoir cinq fois plus de cours, pourvu que leurs objectifs soient bien définis.

Paramètre fluage

Pour commencer, cette petite méthode statique mignonne et innocente pourrait prendre un seul paramètre. Au fur et à mesure que la fonctionnalité augmente, quelques nouveaux paramètres sont ajoutés. D'autres paramètres sont ajoutés en option, de sorte que nous créons des surcharges de la méthode (ou simplement ajoutons des valeurs par défaut, dans les langues qui les supportent). Avant longtemps, nous avons une méthode qui prend 10 paramètres. Seuls les trois premiers sont vraiment requis, les paramètres 4-7 sont optionnels. Mais si le paramètre 6 est spécifié, 7-9 doivent être remplis aussi ... Si nous avions créé une classe dans le seul but de faire ce que faisait cette méthode statique, nous pourrions résoudre cela en prenant en compte les paramètres requis dans le constructeur, et permettant à l'utilisateur de définir des valeurs optionnelles à travers les propriétés, ou des méthodes pour définir plusieurs valeurs interdépendantes en même temps. En outre, si une méthode a atteint ce niveau de complexité, elle doit très probablement être dans sa propre classe.

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

L'un des arguments les plus courants est: Pourquoi exiger que les consommateurs de notre classe créent une instance pour invoquer cette méthode unique, tout en n'ayant aucune utilité pour l'instance par la suite? Créer une instance d'une classe est une opération très très bon marché dans la plupart des langues, donc la vitesse n'est pas un problème. L'ajout d'une ligne de code supplémentaire au consommateur est un faible coût pour jeter les bases d'une solution beaucoup plus maintenable à l'avenir. Et enfin, si vous voulez éviter de créer des instances, créez simplement un wrapper singleton de votre classe qui permet une réutilisation facile - bien que cela rende l'exigence que votre classe soit apatride. Si ce n'est pas sans état, vous pouvez toujours créer des méthodes d'encapsulation statique 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 retourne juste new MyClass();

Seul un Sith traite les absolus

Bien sûr, il y a des exceptions à mon aversion pour les méthodes statiques. Les vraies classes d'utilitaires qui ne présentent aucun risque de ballonnement sont d'excellents cas pour les méthodes statiques - System.Convert à titre d'exemple. Si votre projet est ponctuel et ne nécessite aucune maintenance future, l'architecture globale n'est pas très importante - statique ou non statique, cela n'a pas vraiment d'importance - la vitesse de développement le fait cependant.

Normes, normes, normes!

L'utilisation de méthodes d'instance ne vous empêche pas d'utiliser également des méthodes statiques, et vice versa. Tant qu'il y a un raisonnement derrière la différenciation et qu'il est standardisé. Il n'y a rien de pire que de regarder au-dessus d'une couche d'entreprise s'étalant avec différentes méthodes d'implémentation.


647
2017-10-27 21:01



Lorsque vous décidez de rendre une classe statique ou non statique, vous devez regarder quelles informations vous essayez de représenter. Cela implique un plus »de bas en haut«style de programmation où vous vous concentrez sur les données que vous représentez en premier. Est-ce que la classe que vous écrivez est un objet du monde réel comme un rocher ou une chaise? Ces choses sont physiques et ont des attributs physiques tels que la couleur, le poids qui vous indique que vous pouvez vouloir instancier plusieurs objets avec des propriétés différentes. Je peux vouloir une chaise noire et une chaise rouge en même temps. Si vous avez besoin de deux configurations en même temps, vous savez instantanément que vous voulez l'instancier en tant qu'objet afin que chaque objet puisse être unique et exister en même temps.

D'un autre côté, les fonctions statiques tendent à prêter davantage à des 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 à 'de haut en bas' la programmation. Les méthodes statiques peuvent être utilisées dans ces cas où il n'est pas logique qu'un 'objet' effectue la tâche. En vous obligeant à utiliser des classes, cela facilite le regroupement des fonctionnalités associées, ce qui vous permet de créer du code plus facile à maintenir.

La plupart des classes peuvent être représentées par des éléments statiques ou non statiques, mais en cas de doute, retournez simplement à vos racines OOP et essayez de réfléchir à ce que vous représentez. Est-ce un objet qui effectue une action (une voiture qui peut accélérer, ralentir, tourner) ou quelque chose de plus abstrait (comme afficher une sortie).

Entrez en contact avec votre POO interne et vous ne pouvez jamais vous tromper!


127
2018-02-01 02:50



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


35
2017-10-27 20:57



Si vous utilisez des outils d'analyse de code (par ex. FxCop), il vous recommandera de marquer une méthode static si cette méthode n'accède pas aux données d'instance. La raison 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 ...


21
2017-10-27 21:39



J'ai tendance à utiliser des classes statiques pour les usines. Par exemple, c'est 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é que IoC est appelé avec un accesseur statique. Plus du temps pour moi, si vous pouvez appeler des méthodes statiques sur une classe, c'est tout ce que vous pouvez faire, donc je marque la classe comme statique pour plus de clarté.


12
2017-10-27 21:11



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, apprendre F# m'a fait voir sous un jour nouveau.

Qu'est-ce que je veux dire par là? Eh bien, disons quand travailler quelque super SEC code, je me retrouve avec un tas de classes à une méthode. Je peux simplement tirer ces méthodes dans une classe statique, puis les injecter dans des dépendances en utilisant un délégué. Cela joue aussi bien avec mon injection de dépendance (DI) conteneur de choix Autofac.

Bien sûr, prendre une dépendance directe à une méthode statique est encore d'habitude le mal (il y a des utilisations non-mauvaises).


9
2017-07-01 09:34



J'utilise des classes statiques comme un moyen de définir des «fonctionnalités supplémentaires» qu'un objet d'un type donné pourrait utiliser dans un contexte spécifique. Habituellement, ils se révèlent être des classes d'utilité.

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


8
2017-10-27 21:05