¿Cuál es la mejor manera de almacenar un grupo de constantes que usa mi programa? [cerrado]

97

Tengo varias constantes que mi programa usa ... string's, int' s, double's, etc ... ¿Cuál es la mejor manera de almacenarlas? No creo que quiera una Enum, porque los datos no son todos del mismo tipo y quiero establecer manualmente cada valor. ¿Debería guardarlos todos en una clase vacía? ¿O hay un mejor camino?

Mateo
fuente
18
De la forma que desee, así es como lo necesita.
San Jacinto

Respuestas:

135

Probablemente podría tenerlos en una clase estática, con propiedades estáticas de solo lectura.

public static class Routes
{
    public static string SignUp => "signup";
}
Daniel A. White
fuente
23
+1, pero aún mejor si puede extraerlos de un archivo de recursos para la localización.
Joel Coehoorn
17
Parece un poco prolijo, ¿por qué no cadenas de solo lectura estáticas?
set vacío el
6
¿Por qué readonly y not const? No está estableciendo el valor en tiempo de ejecución, por lo que no es necesario tenerlos como de solo lectura.
Philip Wallace
91
El problema con const es que cualquier ensamblado compilado contra consts obtiene copias locales de esas const cuando se compilan ellos mismos; por lo tanto, si cambia un valor, también debe volver a compilar todos los ensamblados que dependen de su ensamblaje que defina las constantes; por lo tanto, a menudo es más seguro seguir la ruta de solo lectura. Las propiedades en lugar de los valores estáticos públicos le brindan flexibilidad para agregar algo de lógica de programación en el futuro si la necesita (es decir, leer de la localización) sin cambiar la interfaz a sus valores constantes.
cfeduke
11
Como abogado del diablo, debo señalar que la ventaja de const es que puede usarlo en casos de interruptores.
arviman
27

En mi opinión, el uso de una clase llena de constantes está bien para las constantes. Si cambian de vez en cuando, recomiendo usar AppSettings en su configuración y la clase ConfigurationManager en su lugar.

Cuando tengo "constantes" que en realidad son extraídas de AppSettings o similar, siempre tendré una clase de "constantes" que envuelve la lectura del administrador de configuración. Siempre es más significativo tener en Constants.SomeModule.Settinglugar de tener que recurrir directamente a ConfigurationManager.AppSettings["SomeModule/Setting"]cualquier lugar que quiera consumir dicho valor de configuración.

Puntos de bonificación para esta configuración, dado SomeModuleque probablemente sería una clase anidada dentro del archivo Constants, podría usar fácilmente Dependency Injection para inyectar SomeModuledirectamente en las clases que dependen de ella. También puede extraer una interfaz encima SomeModuley luego crear una dependencia ISomeModuleConfigurationen su código de consumo, esto le permitiría desacoplar la dependencia a los archivos Constants e incluso potencialmente facilitar las pruebas, especialmente si estas configuraciones provienen de AppSettings y los cambia usando transformaciones de configuración porque la configuración es específica del entorno.

Chris Marisic
fuente
1
Solo para agregar a esto: la razón es que cuando construye, las constantes usadas de otros ensamblados no se actualizan. Esto significa que si tiene AssemblyA y AssemblyB y B usa una constante de A, el valor se copia, no se hace referencia, por lo que la reconstrucción de A no actualizará B. Esto puede provocar errores extraños.
Camilo Martin
1
@CamiloMartin hay muchas formas de manejar eso, sus "constantes" podrían simplemente leer sólo estáticas para evitar eso, o como dije si cambian más de una vez en una luna azul para usar ConfigurationManager.
Chris Marisic
Sí, solo estaba diciendo que no es solo porque es una convención que debe usar sólo lectura estática, sino porque en realidad puede ser una fuente de confusión. Además, una alternativa a ConfigurationManager son los archivos de recursos: solo tiene que agregar otro archivo de recursos con un código de idioma en el nombre y su código se localiza instantáneamente.
Camilo Martin
el problema es que cuando hace referencia a este ensamblado desde otros ensamblados, tendría que copiar los valores en sus archivos de configuración
simbiont
@symbiont, podría incrustar los archivos de configuración y leerlos del manifiesto en su lugar si lo desea, para compartirlos como un componente de terceros
Chris Marisic
19

Lo que me gusta hacer es lo siguiente (pero asegúrese de leer hasta el final para usar el tipo adecuado de constantes ):

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

Lea esto para saber por qué constpodría no ser lo que desea. Los posibles tipos de constantes son:

  • constcampos. No lo use entre ensamblados ( publico protected) si el valor puede cambiar en el futuro porque el valor estará codificado en tiempo de compilación en esos otros ensamblados. Si cambia el valor, los otros ensamblados usarán el valor anterior hasta que se vuelvan a compilar.
  • static readonly campos
  • static propiedad sin set
Marcel Gosselin
fuente
1
¿Por qué solo lectura si se usa en varios ensamblajes?
Philip Wallace
¿Por qué la función de solo lectura estática funciona mejor con varios ensamblados que const?
Mateo
15
Los valores de constante se copian del ensamblado de origen al código compilado. Esto significa que si tiene que cambiar un valor constante, todos los ensamblados dependientes DEBEN volver a compilarse con la nueva versión. Más seguro y más conveniente de usar solo lectura estática.
cfeduke
6
Los beneficios de const es que se pueden usar en un interruptor
knaki02
11

Esta es la mejor manera en mi opinión. Sin necesidad de propiedades, o solo lectura:

public static class Constants
{
   public const string SomeConstant = "Some value";
}
Philip Wallace
fuente
9
Si va a utilizar const, exponga solo como interno. No haga pública la const (incluso si cree que sus ensamblados no se utilizarán de manera externa a su organización). Además, las propiedades le brindan flexibilidad programática para futuras expansiones sin la necesidad de redefinir su interfaz.
cfeduke
4

Una clase estática vacía es apropiada. Considere el uso de varias clases, de modo que termine con buenos grupos de constantes relacionadas, y no un archivo Globals.cs gigante.

Además, para algunas constantes int, considere la notación:

[Flags]
enum Foo
{
}

Ya que esto permite tratar los valores como banderas .

conjunto vacio
fuente
"Considere usar varias clases, de modo que termine con buenos grupos de constantes relacionadas, y no con un archivo Globals.cs gigante". Creo que esta es la mejor recomendación, ¿no hay algunos patrones de diseño en torno a esto? No conozco a ninguno por su nombre, ¿verdad?
Greg
3

Otro voto para usar web.config o app.config. Los archivos de configuración son un buen lugar para constantes como cadenas de conexión, etc. Prefiero no tener que mirar la fuente para ver o modificar este tipo de cosas. Una clase estática que lee estas constantes de un archivo .config podría ser un buen compromiso, ya que permitirá que su aplicación acceda a estos recursos como si estuvieran definidos en el código, pero aún le brinda la flexibilidad de tenerlos en un formato fácilmente visible / editable. espacio.

3Dave
fuente
2
Una cadena de conexión no es una constante, es una configuración. Podría ser que el OP realmente también signifique configuraciones, en lugar de constantes, pero no veo ninguna evidencia de ello.
Jon Skeet
Siento disentir. Los literales de cadena son constantes por definición. Cambiar la cadena en un archivo de configuración es aproximadamente equivalente a cambiarlo en el código y recompilarlo; Ojalá que lo convierte en una constante? No lo creo.
Salvar el
2
@David - No es cierto. A un compilador no le importa el valor que tenga en su archivo de configuración; esto se lee en tiempo de ejecución.
Philip Wallace
@PhilipW Lo entiendo. Mi punto fue que (en respuesta al comentario de Jon Skeet) una cadena de conexión específica es una constante, como lo son todos los literales de cadena. El hecho de que se pueda cambiar una "constante", ya sea modificando el archivo de configuración y haciendo que su aplicación extraiga el nuevo valor de dicho archivo de configuración, o cambiando el literal en el código que requeriría una recompilación / implementación, no conviértalo en un "escenario". La cadena en sí es constante independientemente de su contenedor. Entiendo y estoy de acuerdo con su punto, simplemente no era lo que estaba diciendo.
Salvar el
1
En mi experiencia, en algún momento del futuro imprevisto, su valor "constante" deberá cambiar incluso si pensaba que nunca lo haría en un millón de años. Creo que esto es mucho más fácil de hacer en un archivo .config que cambiar el código fuente. Todo acaba siendo un escenario al final.
NinjaBomb
1

Sí, una static classpara almacenar constantes estaría bien, excepto para las constantes que están relacionadas con tipos específicos.

bruno conde
fuente
eso es exactamente lo que estoy tratando de hacer. Quiero que se presenten como miembros de la clase a la que pertenecen. pero no quiero agregarlos a las clases porque las constantes varían dependiendo de la empresa para la que estoy haciendo el trabajo. Todavía no he encontrado nada sobre las constantes o propiedades de extensión. pero podría abandonar esta idea porque no quiero que aparezcan como miembros cuando serialice estas clases
symbiont
0

Si estas constantes son referencias de servicio o conmutadores que afectan el comportamiento de la aplicación, las configuraría como configuración de usuario de la aplicación. De esa manera, si es necesario cambiarlos, no es necesario volver a compilarlos y aún puede hacer referencia a ellos a través de la clase de propiedades estáticas.

Properties.Settings.Default.ServiceRef
Aaron
fuente
0

Sugeriría una clase estática con solo lectura estática. Encuentre el fragmento de código a continuación:

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