Qual é a melhor maneira de armazenar um grupo de constantes que meu programa usa? [fechadas]

97

Tenho várias constantes que meu programa usa ... string's, int' s, double's, etc ... Qual é a melhor maneira de armazená-las? Acho que não quero um Enum, porque os dados não são todos do mesmo tipo e quero definir cada valor manualmente. Devo apenas armazená-los todos em uma classe vazia? Ou há um modo melhor?

Mateus
fonte
18
Do jeito que você quiser - é assim que você precisa.
San Jacinto

Respostas:

135

Você provavelmente poderia tê-los em uma classe estática, com propriedades estáticas somente leitura.

public static class Routes
{
    public static string SignUp => "signup";
}
Daniel A. White
fonte
23
+1, mas ainda melhor se você puder extraí-los de um arquivo de recursos para localização.
Joel Coehoorn
17
Parece um pouco prolixo - por que não strings estáticas somente leitura?
emptyset
6
Por que somente leitura e não const? Você não está definindo o valor no tempo de execução, portanto, não há necessidade de tê-los como somente leitura.
Philip Wallace
91
O problema com const é que quaisquer assemblies compilados contra consts obtêm cópias locais desses consts quando eles próprios são compilados; portanto, se você alterar um valor, deverá também recompilar todos os assemblies dependentes de seu assembly definindo as constantes - portanto, geralmente é mais seguro seguir a rota somente leitura. Propriedades, em vez de valores estáticos públicos, oferecem flexibilidade para adicionar alguma lógica de programação no futuro, se necessário (ou seja, ler a partir da localização) sem alterar a interface para seus valores constantes.
cfeduke
11
Como advogado do diabo, devo salientar que a vantagem de const é que você pode usá-lo em casos de troca.
arviman
27

IMO usando uma classe cheia de constantes é bom para constantes. Se eles mudarem de vez em quando, recomendo usar AppSettings em sua configuração e a classe ConfigurationManager.

Quando eu tenho "constantes" que são realmente extraídas de AppSettings ou semelhante, ainda terei uma classe "constantes" que encerra a leitura do gerenciador de configuração. É sempre mais significativo ter ao Constants.SomeModule.Settinginvés de ter que recorrer diretamente a ConfigurationManager.AppSettings["SomeModule/Setting"]qualquer lugar que queira consumir o referido valor de configuração.

Pontos de bônus para esta configuração, uma vez SomeModuleque provavelmente seria uma classe aninhada dentro do arquivo Constants, você poderia facilmente usar a injeção de dependência para injetar SomeModulediretamente em classes que dependem dele. Você também pode extrair uma interface SomeModulee, em seguida, criar uma dependência ISomeModuleConfigurationem seu código de consumo, isso permitiria que você desacoplasse a dependência dos arquivos Constants e até mesmo tornaria os testes mais fáceis, especialmente se essas configurações vierem de AppSettings e você os altera usando transformações de configuração porque as configurações são específicas do ambiente.

Chris Marisic
fonte
1
Só para acrescentar a isto: a razão é que quando você constrói, constantes usadas de outros assemblies não são atualizadas. Isso significa que se você tiver AssemblyA e AssemblyB e B usar uma constante de A, o valor será copiado, não referenciado, portanto, reconstruir A não atualizará B. Isso pode levar a bugs estranhos.
Camilo Martin
1
@CamiloMartin de várias maneiras de lidar com isso, suas "constantes" poderiam apenas readonlys estáticas para evitar isso, ou como eu disse, se elas mudassem mais de uma vez em uma lua azul para usar o ConfigurationManager.
Chris Marisic
Sim, eu estava apenas dizendo que não é apenas porque é uma convenção que você deve usar somente leitura estática, mas porque realmente pode ser uma fonte de confusão. Além disso, uma alternativa ao ConfigurationManager são os arquivos de recursos - você apenas precisa adicionar outro arquivo de recursos com um código de idioma no nome e seu código é localizado instantaneamente.
Camilo Martin
o problema é que quando você faz referência a este assembly de outros assemblies, você teria que copiar os valores em seus arquivos de configuração
simbionte
@symbiont você pode incorporar os arquivos de configuração e lê-los do manifesto se quiser, para compartilhar como um componente de terceiros
Chris Marisic
19

O que eu gosto de fazer é o seguinte (mas certifique-se de ler até o fim para usar o tipo adequado de constantes ):

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

Leia isto para saber por que constpode não ser o que você deseja. Os possíveis tipos de constantes são:

  • constCampos. Não use em assemblies ( publicou protected) se o valor pode mudar no futuro porque o valor será codificado em tempo de compilação nesses outros assemblies. Se você alterar o valor, o valor antigo será usado pelos outros assemblies até que sejam recompilados.
  • static readonly Campos
  • static propriedade sem set
Marcel Gosselin
fonte
1
Por que somente leitura se usado em vários assemblies?
Philip Wallace
Por que estático somente leitura funciona melhor com vários assemblies do que const?
Mateus
15
Os valores Const são copiados do assembly de origem para o código compilado. Isso significa que se você tiver que alterar um valor const, todos os assemblies dependentes DEVEM ser recompilados com a nova versão. Mais seguro e conveniente de usar somente leitura estática.
cfeduke
6
Os benefícios de const é que eles podem ser usados ​​em um switch
knaki02
11

Esta é a melhor forma IMO. Não há necessidade de propriedades ou somente leitura:

public static class Constants
{
   public const string SomeConstant = "Some value";
}
Philip Wallace
fonte
9
Se você for usar const, exponha apenas como interno. Não torne const público (mesmo se você achar que seus assemblies não serão usados ​​externamente à sua organização). Além disso, as propriedades fornecem flexibilidade programática para expansão futura sem a necessidade de redefinir sua interface.
cfeduke
4

Uma classe estática vazia é apropriada. Considere o uso de várias classes, de modo que você termine com bons grupos de constantes relacionadas, e não um arquivo gigante Globals.cs.

Além disso, para algumas constantes int, considere a notação:

[Flags]
enum Foo
{
}

Isso permite tratar os valores como sinalizadores .

conjunto vazio
fonte
"Considere o uso de várias classes, de modo que você termine com bons grupos de constantes relacionadas, e não um arquivo gigante Globals.cs." Eu acredito que esta é a melhor recomendação, não existem alguns padrões de design em torno disso? Não conheço nenhum pelo nome, e você?
greg
3

Outro voto para usar web.config ou app.config. Os arquivos de configuração são um bom lugar para constantes como strings de conexão, etc. Prefiro não ter que olhar a fonte para ver ou modificar esses tipos de coisas. Uma classe estática que lê essas constantes de um arquivo .config pode ser um bom meio-termo, pois permitirá que seu aplicativo acesse esses recursos como se estivessem definidos no código, mas ainda oferece a flexibilidade de tê-los em um formato facilmente visualizável / editável espaço.

3Dave
fonte
2
Uma string de conexão não é uma constante, é uma configuração. Pode ser que o OP realmente signifique configurações também, em vez de constantes, mas não vejo nenhuma evidência disso.
Jon Skeet
Eu peço desculpa mas não concordo. Literais de string são constantes por definição. Alterar a string em um arquivo de configuração é aproximadamente equivalente a alterá-la no código e recompilar; Oxalá que não torná-lo uma constante? Acho que não.
3Dave
2
@David - Não é verdade. Um compilador não se preocupa com o valor que você tem em seu arquivo de configuração - isso é lido em tempo de execução.
Philip Wallace
@PhilipW Eu entendo isso. Meu ponto é que (em resposta ao comentário de Jon Skeet) uma string de conexão específica é uma constante, como todos os literais de string são. O fato de uma "constante" poder ser alterada - seja modificando o arquivo de configuração e fazendo com que seu aplicativo extraia o novo valor do referido arquivo de configuração, ou alterando o literal no código que exigiria uma recompilação / implantação - não torná-lo um "cenário". A string em si é constante, independentemente de seu contêiner. Eu entendo e concordo com seu ponto - simplesmente não era o que eu estava dizendo.
3Dave
1
Em minha experiência, em algum momento no futuro imprevisto, seu valor "constante" precisará mudar, mesmo que você pensasse que nunca mudaria em um milhão de anos. Acho que isso é muito mais fácil de fazer em um arquivo .config do que alterar o código-fonte. Tudo acaba sendo cenário no final.
NinjaBomb
1

Sim, um static classpara armazenar constantes seria suficiente, exceto para constantes relacionadas a tipos específicos.

bruno conde
fonte
isso é exatamente o que estou tentando fazer. quero que apareçam como membros da classe a que se destinam. mas não quero adicioná-los às classes porque as constantes variam dependendo da empresa para a qual estou fazendo o trabalho. ainda não encontrei nada sobre constantes de extensão ou propriedades. mas posso abandonar essa ideia porque não quero que eles apareçam como membros quando serializo essas classes
simbionte
0

Se essas constantes forem referências de serviço ou opções que afetam o comportamento do aplicativo, eu as configuraria como configurações do usuário do aplicativo. Dessa forma, se eles precisarem ser alterados, você não precisará recompilar e ainda poderá referenciá-los por meio da classe de propriedades estáticas.

Properties.Settings.Default.ServiceRef
Aaron
fonte
0

Eu sugeriria uma classe estática com somente leitura estática. Encontre o snippet de código abaixo:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
KAPIL SHARMA
fonte