Quelle est la meilleure façon de stocker un groupe de constantes que mon programme utilise? [fermé]


97

J'ai différentes constantes que mon programme utilise ... string's, int' s, double's, etc ... Quelle est la meilleure façon de les stocker? Je ne pense pas que je veuille un Enum, car les données ne sont pas toutes du même type, et je veux définir manuellement chaque valeur. Dois-je simplement les stocker tous dans une classe vide? Ou y a-t-il un meilleur moyen?


18
Comme vous le voulez, c'est ainsi que vous en avez besoin.
San Jacinto

Réponses:


135

Vous pourriez probablement les avoir dans une classe statique, avec des propriétés statiques en lecture seule.

public static class Routes
{
    public static string SignUp => "signup";
}

23
+1, mais encore mieux si vous pouvez les extraire d'un fichier de ressources pour la localisation.
Joel Coehoorn

17
Semble un peu verbeux - pourquoi pas des chaînes statiques en lecture seule?
emptyset

6
Pourquoi en lecture seule et non const? Vous ne définissez pas la valeur au moment de l'exécution, il n'est donc pas nécessaire de les avoir en lecture seule.
Philip Wallace

91
Le problème avec const est que tous les assemblys compilés avec des consts obtiennent des copies locales de ces consts lorsqu'ils sont eux-mêmes compilés; donc si vous modifiez une valeur, vous devez également recompiler tous les assemblys qui dépendent de votre assemblage définissant les constantes - il est donc souvent plus sûr de suivre la voie en lecture seule. Les propriétés au lieu des valeurs statiques publiques vous donnent la flexibilité d'ajouter une logique de programmation à l'avenir si vous en avez besoin (c'est-à-dire lire à partir de la localisation) sans changer l'interface avec vos valeurs constantes.
cfeduke

11
En tant qu'avocat du diable, je dois souligner que l'avantage de const est que vous pouvez l'utiliser dans des cas de commutation.
arviman

27

IMO en utilisant une classe pleine de constantes est très bien pour les constantes. S'ils changent de manière semi-occasionnelle, je recommande d'utiliser AppSettings dans votre configuration et la classe ConfigurationManager à la place.

Quand j'ai des "constantes" qui sont réellement extraites d'AppSettings ou similaires, j'aurai toujours une classe "constantes" qui encapsule la lecture du gestionnaire de configuration. C'est toujours plus significatif d'avoir Constants.SomeModule.Settingau lieu d'avoir à recourir directement àConfigurationManager.AppSettings["SomeModule/Setting"] n'importe quel endroit qui veut consommer ladite valeur de réglage.

Points bonus pour cette configuration, car il SomeModules'agirait probablement d'une classe imbriquée dans le fichier Constantes, vous pouvez facilement utiliser l'injection de dépendances pour injecter soitSomeModule directement dans les classes qui en dépendent. Vous pouvez même extraire une interface par-dessus SomeModuleet créer une dépendance à ISomeModuleConfigurationdans votre code de consommation, cela vous permettrait alors de découpler la dépendance aux fichiers Constants, et même potentiellement de rendre les tests plus faciles, surtout si ces paramètres proviennent d'AppSettings et vous les modifiez à l'aide de transformations de configuration car les paramètres sont spécifiques à l'environnement.


1
Juste pour ajouter à ceci: la raison est que lorsque vous construisez, les constantes utilisées à partir d'autres assemblys ne sont pas mises à jour. Cela signifie que si vous avez AssemblyA et AssemblyB et que B utilise une constante de A, la valeur est copiée, non référencée, donc la reconstruction de A ne mettra pas à jour B. Cela peut conduire à des bogues étranges.
Camilo Martin

1
@CamiloMartin de nombreuses façons de gérer cela, vos «constantes» pourraient simplement lire statiquement pour éviter cela, ou comme je l'ai dit si elles changent plus d'une fois dans une lune bleue pour utiliser le ConfigurationManager.
Chris Marisic

Oui, je disais simplement que ce n'est pas seulement parce que c'est une convention que vous devez utiliser la lecture statique en lecture seule, mais parce que cela peut en fait être une source de confusion. En outre, une alternative à ConfigurationManager est les fichiers de ressources - il vous suffit d'ajouter un autre fichier de ressources avec un code de langue dans le nom et votre code est instantanément localisé.
Camilo Martin

le problème est que lorsque vous référencez cet assemblage à partir d'autres assemblys, vous devrez copier les valeurs dans leurs fichiers de configuration
symbiont

@symbiont, vous pouvez intégrer les fichiers de configuration et les lire à la place du manifeste si vous le souhaitez, pour la sharabilité en tant que composant tiers
Chris Marisic

19

Ce que j'aime faire est ce qui suit (mais assurez-vous de lire jusqu'à la fin pour utiliser le type de constantes approprié ):

internal static class ColumnKeys
{
    internal const string Date = "Date";
    internal const string Value = "Value";
    ...
}

Lisez ceci pour savoir pourquoi constce n'est pas ce que vous voulez. Les types de constantes possibles sont:

  • constdes champs. N'utilisez pas entre les assemblys ( publicou protected) si la valeur peut changer à l'avenir, car la valeur sera codée en dur au moment de la compilation dans ces autres assemblys. Si vous modifiez la valeur, l'ancienne valeur sera utilisée par les autres assemblys jusqu'à ce qu'ils soient recompilés.
  • static readonly des champs
  • static propriété sans set

1
Pourquoi en lecture seule s'il est utilisé dans plusieurs assemblys?
Philip Wallace

Pourquoi la lecture seule statique fonctionne-t-elle mieux avec plusieurs assemblys que const?
Matthieu

15
Les valeurs Const sont copiées de l'assembly source dans le code compilé. Cela signifie que si vous devez changer une valeur const, tous les assemblys dépendants DOIVENT être recompilés avec la nouvelle version. Plus sûr et plus pratique à utiliser en lecture seule statique.
cfeduke

6
Les avantages de const sont qu'ils peuvent être utilisés dans un commutateur
knaki02

11

C'est la meilleure façon IMO. Pas besoin de propriétés, ou en lecture seule:

public static class Constants
{
   public const string SomeConstant = "Some value";
}

9
Si vous comptez utiliser const, exposez uniquement en interne. Ne rendez pas const public (même si vous pensez que vos assemblys ne seront pas utilisés à l'extérieur de votre organisation). Les propriétés vous offrent également une flexibilité programmatique pour une expansion future sans qu'il soit nécessaire de redéfinir votre interface.
cfeduke

4

Une classe statique vide est appropriée. Pensez à utiliser plusieurs classes, de sorte que vous vous retrouviez avec de bons groupes de constantes associées, et non un fichier géant Globals.cs.

De plus, pour certaines constantes int, considérez la notation:

[Flags]
enum Foo
{
}

Comme cela permet de traiter les valeurs comme des drapeaux .


"Pensez à utiliser plusieurs classes, de sorte que vous vous retrouvez avec de bons groupes de constantes liées, et pas un fichier Globals.cs géant." Je pense que c'est la meilleure recommandation, n'y a-t-il pas des modèles de conception autour de cela? Je n'en connais pas de nom, n'est-ce pas?
greg

3

Un autre vote pour l'utilisation de web.config ou app.config. Les fichiers de configuration sont un bon endroit pour les constantes comme les chaînes de connexion, etc. Je préfère ne pas avoir à regarder la source pour voir ou modifier ce type de choses. Une classe statique qui lit ces constantes à partir d'un fichier .config peut être un bon compromis, car elle permettra à votre application d'accéder à ces ressources comme si elles étaient définies dans le code, mais vous donnera tout de même la flexibilité de les avoir dans un format facilement consultable / modifiable espace.


2
Une chaîne de connexion n'est pas une constante, c'est un paramètre. Il se peut que l'OP signifie vraiment des paramètres aussi, plutôt que des constantes, mais je ne vois aucune preuve pour cela.
Jon Skeet

Je ne suis pas d'accord. Les littéraux de chaîne sont des constantes par définition. Changer la chaîne dans un fichier de configuration équivaut à peu près à la changer dans le code et à la recompiler; cela ne ferait-il pas une constante? Je ne pense pas.
3Dave

2
@David - Ce n'est pas vrai. Un compilateur ne se soucie pas de la valeur que vous avez dans votre fichier de configuration - cela est lu au moment de l'exécution.
Philip Wallace

@PhilipW Je comprends cela. Mon point était que (en réponse au commentaire de Jon Skeet) une chaîne de connexion spécifique est une constante, comme tous les littéraux de chaîne. Le fait qu'une "constante" puisse être modifiée - que ce soit en modifiant le fichier de configuration et en demandant à votre application d'extraire la nouvelle valeur dudit fichier de configuration, ou en changeant le littéral dans le code qui nécessiterait une recompilation / déploiement - ne en faire un "paramètre". La chaîne elle-même est constante quel que soit son conteneur. Je comprends et suis d'accord avec votre argument - ce n'était tout simplement pas ce que je disais.
3Dave

1
D'après mon expérience, à un moment donné dans un avenir imprévu, votre valeur «constante» devra changer même si vous pensiez qu'elle ne le ferait jamais dans un million d'années. Je pense que c'est beaucoup plus facile à faire dans un fichier .config que de changer le code source. Tout finit par être un décor à la fin.
NinjaBomb

1

Oui, un static classpour stocker des constantes serait très bien, sauf pour les constantes liées à des types spécifiques.


c'est exactement ce que j'essaye de faire. je veux qu'ils se présentent comme membres de la classe pour laquelle ils sont. mais je ne veux pas les ajouter aux classes car les constantes varient en fonction de l'entreprise pour laquelle je fais le travail. Je n'ai encore rien trouvé sur les constantes ou propriétés d'extension. mais je pourrais abandonner cette idée parce que je ne veux pas qu'ils apparaissent en tant que membres lorsque je sérialise ces classes
symbiont

0

Si ces constantes sont des références de service ou des commutateurs qui affectent le comportement de l'application, je les configurerais en tant que paramètres utilisateur de l'application. De cette façon, s'ils doivent être modifiés, vous n'avez pas à les recompiler et vous pouvez toujours les référencer via la classe de propriétés statiques.

Properties.Settings.Default.ServiceRef

0

Je suggérerais une classe statique avec lecture seule statique. Veuillez trouver l'extrait de code ci-dessous:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
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.