Qual è il modo migliore per memorizzare un gruppo di costanti utilizzate dal mio programma? [chiuso]


97

Ho varie costanti che il mio programma usa ... string's int, double' s, ecc ... Qual è il modo migliore per memorizzarle? Non penso di volerlo Enum, perché i dati non sono tutti dello stesso tipo e voglio impostare manualmente ogni valore. Dovrei semplicemente archiviarli tutti in una classe vuota? O c'è un modo migliore?


18
In qualsiasi modo tu lo voglia, è così che ne hai bisogno.
San Jacinto

Risposte:


135

Probabilmente potresti averli in una classe statica, con proprietà statiche di sola lettura.

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

23
+1, ma ancora meglio se puoi estrarli da un file di risorse per la localizzazione.
Joel Coehoorn

17
Sembra un po 'prolisso: perché non stringhe di sola lettura statica?
emptyset

6
Perché readonly e non const? Non stai impostando il valore in fase di esecuzione, quindi non è necessario averli in sola lettura.
Philip Wallace

91
Il problema con const è che qualsiasi assembly compilato su const ottiene copie locali di tali const quando vengono compilati; quindi, se si modifica un valore, è necessario ricompilare anche tutti gli assembly dipendenti dal proprio assembly definendo le costanti, quindi è spesso più sicuro seguire il percorso di sola lettura. Le proprietà invece dei valori statici pubblici ti danno la flessibilità di aggiungere un po 'di logica di programmazione in futuro se ne hai bisogno (cioè leggere dalla localizzazione) senza cambiare l'interfaccia ai tuoi valori costanti.
cfeduke

11
Come avvocato del diavolo, devo sottolineare che il vantaggio di const è che puoi usarlo in casi di cambio.
arviman

27

IMO che utilizza una classe piena di costanti va bene per le costanti. Se cambieranno semi-occasionalmente, consiglio di utilizzare AppSettings nella tua configurazione e nella classe ConfigurationManager.

Quando ho "costanti" effettivamente estratte da AppSettings o simili, avrò sempre una classe "costanti" che avvolge la lettura dal gestore di configurazione. È sempre più significativo avere Constants.SomeModule.Settinginvece di dover ricorrere direttamente a ConfigurationManager.AppSettings["SomeModule/Setting"]qualsiasi luogo che voglia consumare detto valore di impostazione.

Punti bonus per questa configurazione, poiché SomeModulesarebbe probabilmente una classe nidificata all'interno del file Constants, potresti facilmente usare Dependency Injection per iniettare SomeModuledirettamente nelle classi che dipendono da esso. Potresti anche estrarre un'interfaccia sopra SomeModulee quindi creare una dipendenza ISomeModuleConfigurationnel codice in uso, questo ti consentirebbe di disaccoppiare la dipendenza dai file Constants e persino potenzialmente rendere più semplice il test, specialmente se queste impostazioni provengono da AppSettings e li si modifica utilizzando le trasformazioni di configurazione perché le impostazioni sono specifiche dell'ambiente.


1
Solo per aggiungere a questo: il motivo è che quando si crea, le costanti utilizzate da altri assembly non vengono aggiornate. Ciò significa che se hai AssemblyA e AssemblyB e B usa una costante da A, il valore viene copiato, non referenziato, quindi la ricostruzione di A non aggiornerà B. Questo può portare a strani bug.
Camilo Martin

1
@CamiloMartin molti modi per gestirlo, le tue "costanti" potrebbero semplicemente essere in lettura statica per evitarlo, o come ho detto se cambiano più di una volta in una luna blu per usare il ConfigurationManager.
Chris Marisic

Sì, stavo solo dicendo che non è solo perché è una convenzione che dovresti usare in sola lettura statica, ma perché in realtà può essere fonte di confusione. Inoltre, un'alternativa a ConfigurationManager sono i file di risorse: devi solo aggiungere un altro file di risorse con un codice della lingua nel nome e il tuo codice viene localizzato immediatamente.
Camilo Martin

il problema è che quando fai riferimento a questo assembly da altri assembly, dovresti copiare i valori nei loro file di configurazione
simbiont

@symbiont potresti incorporare i file di configurazione e leggerli invece dal manifest, se lo desideri, per la condivisione come componente di terze parti
Chris Marisic

19

Quello che mi piace fare è il seguente (ma assicurati di leggere fino alla fine per utilizzare il tipo corretto di costanti ):

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

Leggi questo per sapere perché constpotrebbe non essere quello che desideri. I possibili tipi di costanti sono:

  • constcampi. Non usare tra gli assembly ( publico protected) se il valore potrebbe cambiare in futuro perché il valore verrà codificato in fase di compilazione in quegli altri assembly. Se si modifica il valore, il vecchio valore verrà utilizzato dagli altri assembly fino a quando non vengono ricompilati.
  • static readonly campi
  • static proprietà senza set

1
Perché in sola lettura se utilizzato su più assembly?
Philip Wallace

Perché la sola lettura statica funziona meglio con più assembly rispetto a const?
Matteo

15
I valori cost vengono copiati dall'assembly di origine nel codice compilato. Ciò significa che se è necessario modificare un valore const, tutti gli assembly dipendenti DEVONO essere ricompilati con la nuova versione. Più sicuro e più comodo da usare di sola lettura statica.
cfeduke

6
I vantaggi di const è che possono essere utilizzati in uno switch
knaki02

11

Questo è il modo migliore IMO. Nessuna necessità di proprietà o sola lettura:

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

9
Se intendi utilizzare const, esponi solo come interno. Non rendere pubblico const (anche se pensi che i tuoi assembly non verranno utilizzati all'esterno della tua organizzazione). Inoltre, le proprietà offrono flessibilità programmatica per future espansioni senza la necessità di ridefinire l'interfaccia.
cfeduke

4

È appropriata una classe statica vuota. Prendi in considerazione l'utilizzo di diverse classi, in modo da ottenere buoni gruppi di costanti correlate e non un file Globals.cs gigante.

Inoltre, per alcune costanti int, considera la notazione:

[Flags]
enum Foo
{
}

Poiché ciò consente di trattare i valori come flag .


"Prendi in considerazione l'utilizzo di più classi, in modo da ottenere buoni gruppi di costanti correlate e non un file Globals.cs gigante." Credo che questa sia la migliore raccomandazione, non ci sono alcuni modelli di design attorno a questo? Non ne conosco nessuno per nome, vero?
greg

3

Un altro voto per l'utilizzo di web.config o app.config. I file di configurazione sono un buon posto per costanti come le stringhe di connessione, ecc. Preferisco non dover guardare i sorgenti per visualizzare o modificare questo tipo di cose. Una classe statica che legge queste costanti da un file .config potrebbe essere un buon compromesso, poiché consentirà alla tua applicazione di accedere a queste risorse come se fossero definite nel codice, ma ti darà comunque la flessibilità di averle in modo facilmente visualizzabile / modificabile spazio.


2
Una stringa di connessione non è una costante, è un'impostazione. Potrebbe essere che l'OP significhi davvero anche impostazioni, piuttosto che costanti, ma non ne vedo alcuna prova.
Jon Skeet,

Mi permetto di dissentire. I letterali stringa sono costanti per definizione. Modificare la stringa in un file di configurazione equivale all'incirca a cambiarla nel codice e ricompilarla; Volesse che lo rende una costante? Non credo proprio.
Salva il

2
@David - Non è vero. Un compilatore non si preoccupa del valore che hai nel tuo file di configurazione: questo viene letto in fase di esecuzione.
Philip Wallace,

@PhilipW Lo capisco. Il punto era che (in risposta al commento di Jon Skeet) una specifica stringa di connessione è una costante, come lo sono tutte le stringhe letterali. Il fatto che una "costante" possa essere cambiata - sia modificando il file di configurazione e facendo in modo che la tua app prenda il nuovo valore da detto file di configurazione, o cambiando il codice letterale che richiederebbe una ricompilazione / distribuzione - non renderlo un "ambiente". La stringa stessa è costante indipendentemente dal suo contenitore. Capisco e sono d'accordo con il tuo punto - semplicemente non era quello che stavo dicendo.
Salva il

1
Nella mia esperienza, a un certo punto in un futuro imprevisto, il tuo valore "costante" dovrà cambiare anche se pensavi che non sarebbe mai cambiato tra un milione di anni. Penso che questo sia molto più facile da fare in un file .config che cambiare il codice sorgente. Alla fine, tutto finisce per essere un'ambientazione.
NinjaBomb

1

Sì, una static classper la memorizzazione delle costanti andrebbe bene, ad eccezione delle costanti correlate a tipi specifici.


è esattamente quello che sto cercando di fare. Voglio che si presentino come membri della classe per cui sono. ma non voglio aggiungerli alle classi perché le costanti variano a seconda dell'azienda per cui lavoro. non ho ancora trovato nulla sulle costanti di estensione o sulle proprietà. ma potrei abbandonare questa idea perché non voglio che si presentino come membri quando serializzo queste classi
simbionte

0

Se queste costanti sono riferimenti di servizio o interruttori che influenzano il comportamento dell'applicazione, le configurerei come impostazioni utente dell'applicazione. In questo modo, se devono essere modificati, non è necessario ricompilarli e puoi comunque fare riferimento a essi tramite la classe delle proprietà statiche.

Properties.Settings.Default.ServiceRef

0

Suggerirei una classe statica con sola lettura statica. Trova lo snippet di codice di seguito:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.