C # Classe statique vs struct pour les chaînes prédéfinies

Un collègue vient de créer la construction suivante en C # (l’exemple de code est simplifié). Son but était de raccourcir la notation pour toutes les chaînes prédéfinies dans le rest du code.

public struct PredefinedSsortingngs { public const ssortingng VeryLongName = "Very Long Name"; public const ssortingng AnotherVeryLongName = "Another Very Long Name"; public const ssortingng TheLastVeryLongName = "The Last Very Long Name"; } public static void MethodThatUsesTheNames() { Console.WriteLine(PredefinedSsortingngs.VeryLongName); Console.WriteLine(PredefinedSsortingngs.AnotherVeryLongName); Console.WriteLine(PredefinedSsortingngs.TheLastVeryLongName); } 

Bien que cela semble fonctionner correctement pour lui, je ne peux pas m’empêcher de me demander s’il aurait dû utiliser une classe statique au lieu d’une structure ou s’il existe un moyen plus élégant d’y parvenir.

Quelle serait la façon préférée de le faire? Veuillez aussi expliquer pourquoi.

Avec la solution struct , il n’y a rien pour arrêter un autre code faisant du new PredefinedSsortingngs() , qui ne fera rien de mal , mais c’est quelque chose qu’il est sémantiquement déroutant d’autoriser. Avec une classe statique, le compilateur interdira la création pour vous. Et il va sans dire que la classe statique est la méthode privilégiée pour fournir des constantes dans le Framework.

edit pour append, j’ai dit que la deuxième partie sans preuve – j’ai depuis cherché et raisonnablement rapidement trouvé System.Net.Mime.DispositionTypeNames et System.Net.WebRequestMethods.Http .

Je préférerais que les chaînes soient toutes dans un fichier de ressources et non incorporées dans le code – principalement pour des raisons d’internationalisation. On peut alors y accéder via une classe statique avec les valeurs en tant que membres de la propriété.

Outre une static class et une struct static class , pourquoi ne pas utiliser resource fichiers de resource pour des chaînes constantes? Celles-ci peuvent être consultées très facilement sous le nom SomeNamespace.ResourceName.KeyName , et selon l’endroit où elles se trouvent dans votre projet, elles peuvent être gérées de manière externe sans recompilation si nécessaire …

Règle simple: n’utilisez jamais de structures tant que vous n’avez pas d’autre choix.

Les constantes ont quelques inconvénients:

  • seuls des types simples peuvent être utilisés (chaînes, chiffres, etc.)
  • les constantes sont injectées dans les assemblages de référence. Si vous recomstackz l’assemblage avec des constantes et ne recomstackz pas l’assemblage qui utilise des constantes, vous aurez des problèmes

J’écrirais votre code comme ceci (notez également le renommage du refactoring):

 public static class KnownNames { public static readonly ssortingng VeryLong = "Very Long Name"; public static readonly ssortingng AnotherVeryLong = "Another Very Long Name"; public static readonly ssortingng TheLastVeryLong = "The Last Very Long Name"; } 

Il semble que vous cherchiez un fichier de ressources (.resx). C’est un endroit décent pour stocker de telles chaînes, et en résumant vos chaînes dans un fichier .resx, il sera plus facile de localiser votre application à l’avenir. La page MSDN à http://msdn.microsoft.com/en-us/library/1ztca10y.aspx est un bon début pour plus d’informations.

Il n’y a rien de mal fonctionnel avec ce code. Mais stylistiquement, je suis d’accord pour dire qu’une classe statique est préférable. Une classe statique déclare que le but du type est de ne contenir que des données statiques / constantes.

N’oubliez pas la recommandation selon laquelle une taille de structure doit être d’environ 16 octets. Avec un système 32 bits, il y a 4 références System.Ssortingng. Je dirais que vous êtes mieux avec une classe statique si le nombre de chaînes augmente.

Je pense que la statique est meilleure et voici mon raisonnement. Si ce code réside dans une bibliothèque et qu’un autre morceau de code consum cette bibliothèque, si la valeur des champs constants change, cette bibliothèque doit non seulement être recompilée (duh), mais vous devrez recomstackr le code en utilisant cette bibliothèque. bibliothèque aussi. La raison en est que la compilation insère les valeurs constantes partout où vous les référencez. Si vous utilisez du statique, vous n’aurez pas ce problème, car vous faites référence au champ et non à la valeur .

la classe statique semble être la meilleure solution car elle est la plus standard et la plus attendue. Je pensais que les versions de struct / const pourraient être plus rapides mais après quelques tests, elles ne l’étaient pas.

Voici les résultats de mon test rapide qui comprend la longueur, compare, concat, copy, indexOf et Subssortingng. Il a été exécuté sous .Net 4.0 dans la version sans un débogueur attaché.

  .Net 3.0 .Net 4.0 static class with static read-only ssortingng: 0.217 0.364 seconds static class with const ssortingng: 0.211 0.361 seconds struct with static read-only ssortingng: 0.211 0.372 seconds struct with const ssortingng: 0.214 0.371 seconds Properties.Resources ssortingng: 1.173 1.268 seconds 

Elles concernaient toutes la même performance, sauf en utilisant un fichier de ressources, ce qui est plus lent. Bien que Properties.Resources soit plus lent, il n’est pas stocké dans l’exécutable, ce qui peut être plus approprié dans certains cas. Donc, utilisez soit la “classe statique” ou Properties.Resources stockant des chaînes à mon avis.

Les structures sont normalement évitées à moins qu’elles ne répondent à certains critères détaillés dans cette réponse .

Comme votre collègue ne l’utilise pas pour stocker une valeur, il devrait utiliser une classe et non une structure.

Dans ma pratique à cette fin, nous utilisons Dictionary . Où enumNameType est le type différent de noms que vous pouvez avoir (dans votre cas) … Ce dictionnaire est encapsulé dans une classe statique et est mis en cache – nous le créons juste la première fois que nous l’utilisons et renvoyons le même object …

J’espère que cela vous sera utile aussi!

J’utilise aussi des structures pour les constantes, mais uniquement pour un usage interne, pas pour les API publiques. Cela semble naturel puisque les énumérations sont également converties en structures.

Le simple fait que vous soyez autorisé à créer un nouvel object destiné à être une constante est une preuve évidente d’une mauvaise pratique (généralement). Je dis “habituellement” parce que .NET utilise le concept de temps en temps, même si on ne sait pas pourquoi.

Bien sûr, vous pouvez toujours faire des choses comme ça:

 public class Foo { public struct Bar { public static double A = 100; public Bar(double a) { A = a; } } } 

Ce qui justifie techniquement la création de Bar ; Cependant, il n’y a aucune garantie que la constante Bar soit identique (même dans un environnement mono-thread) et est finalement peu utile.