enum - define c#




Statico readonly vs const (10)

Ho letto in giro sui campi const e static readonly . Abbiamo alcune classi che contengono solo valori costanti. Utilizzato per varie cose nel nostro sistema. Quindi mi chiedo se la mia osservazione sia corretta:

Questo tipo di valori costanti dovrebbe sempre essere static readonly per tutto ciò che è pubblico? E usi solo const per valori interni / protetti / privati?

Che cosa mi consiglia? Dovrei forse anche non usare static readonly campi static readonly , ma piuttosto usare le proprietà forse?


Const: Const non è altro che "costante", una variabile di cui il valore è costante ma al momento della compilazione. Ed è obbligatorio assegnare un valore ad esso. Di default un const è statico e non possiamo cambiare il valore di una variabile const nell'intero programma.

Statico ReadOnly: A Static Readonly il valore della variabile di tipo può essere assegnato in fase di esecuzione o assegnato in fase di compilazione e modificato in fase di esecuzione. Ma il valore di questa variabile può essere modificato solo nel costruttore statico. E non può essere ulteriormente modificato. Può cambiare solo una volta in fase di esecuzione

Riferimento: c-sharpcorner


Alcune altre cose

const int a

  • deve essere inizializzato
  • l'inizializzazione deve essere in fase di compilazione

readonly int a

  • può usare il valore predefinito, senza inizializzare
  • l'inizializzazione può essere in fase di esecuzione

La mia preferenza è di usare const ogni volta che posso, che come detto sopra è limitato a espressioni letterali o qualcosa che non richiede una valutazione.

Se mi scaldi contro quella limitazione, allora ricado alla statica di sola lettura , con un avvertimento. Generalmente utilizzerei una proprietà statica pubblica con un getter e un campo privato statico di backing privato come Marc menziona here .


La parola chiave readonly è diversa dalla parola chiave const . Un campo const può essere inizializzato solo alla dichiarazione del campo. Un campo di readonly può essere inizializzato o alla dichiarazione o in un costruttore. Pertanto, i campi di readonly possono avere valori diversi a seconda del costruttore utilizzato. Inoltre, mentre un campo const è una costante in fase di compilazione, il campo readonly può essere utilizzato per le costanti di runtime

Riferimento MSDN breve e chiaro qui


Questo è solo un supplemento alle altre risposte. Non li ripeterò (ora quattro anni dopo).

Ci sono situazioni in cui un const e un non-const hanno una semantica diversa. Per esempio:

const int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

stampa True , mentre:

static readonly int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

scrive False .

Il motivo è che il metodo x.Equals ha due overload, uno che richiede un short ( System.Int16 ) e uno che accetta un object ( System.Object ). Ora la domanda è se uno o entrambi si applicano al mio argomento y .

Quando y è una costante in fase di compilazione (letterale), il caso const , diventa importante che esista una conversione implicita da int a short condizione che l' int sia una costante e che il compilatore C # verifichi che il suo valore sia all'interno il raggio di un short (che è 42 ). Vedi Conversazioni con espressioni costanti implicite nella specifica del linguaggio C #. Quindi entrambi i sovraccarichi devono essere considerati. Il sovraccarico Equals(short) è preferito (qualsiasi short è un object , ma non tutti gli object sono short ). Quindi y viene convertito in short e viene usato quel overload. Quindi Equals confronta due short di valore identico, e ciò dà true .

Quando y non è una costante, non esiste alcuna conversione implicita da int a short . Questo perché in generale un int può essere troppo grande per essere inserito in un short . (Esiste una conversione esplicita , ma non ho detto Equals((short)y) , quindi non è rilevante.) Vediamo che si applica solo un sovraccarico, quello Equals(object) . Quindi y è inscatolato per object . Quindi Equals sta per confrontare un System.Int16 con un System.Int32 e, poiché i tipi di runtime non sono nemmeno d'accordo, ciò produrrà false .

Concludiamo che in alcuni (rari) casi, la modifica di un membro di tipo const in un campo static readonly (o l'altro modo, quando è possibile) può modificare il comportamento del programma.


Un campo statico di sola lettura è vantaggioso quando si espone ad altri assiemi un valore che potrebbe cambiare in una versione successiva.

Ad esempio, supponiamo che l'assemblaggio X esponga una costante come segue:

public const decimal ProgramVersion = 2.3;

Se l'assemblaggio Y riferimento a X e usa questa costante, il valore 2.3 sarà cotto nell'assemblaggio Y momento della compilazione. Ciò significa che se X viene in seguito ricompilato con la costante impostata su 2.4, Y utilizzerà comunque il vecchio valore di 2.3 finché non viene ricompilato Y Un campo statico di sola lettura evita questo problema.

Un altro modo di guardare a questo è che qualsiasi valore che potrebbe cambiare in futuro non è costante per definizione, e quindi non dovrebbe essere rappresentato come uno.


const:

  1. il valore dovrebbe essere dato al momento della dichiarazione
  2. compilare costante di tempo

sola lettura:

  1. il valore può essere dato in base alla dichiarazione o durante il runtime utilizzando i costruttori. Il valore può variare a seconda del costruttore utilizzato.
  2. tempo costante di esecuzione

const e readonly sono simili, ma non sono esattamente gli stessi.

Un campo const è una costante in fase di compilazione, il che significa che quel valore può essere calcolato in fase di compilazione. Un campo readonly abilita scenari aggiuntivi in ​​cui alcuni codici devono essere eseguiti durante la costruzione del tipo. Dopo la costruzione, un campo di readonly non può essere modificato.

Ad esempio, i membri const possono essere utilizzati per definire membri come:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

Poiché valori come 3.14 e 0 sono costanti in fase di compilazione. Tuttavia, considera il caso in cui definisci un tipo e vuoi fornire alcune istanze prefabbricate. Ad esempio, potresti voler definire una classe di colori e fornire "costanti" per i colori comuni come nero, bianco, ecc. Non è possibile farlo con i membri const, poiché i lati a destra non sono costanti in fase di compilazione. Uno potrebbe farlo con membri statici regolari:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red   = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue  = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}

Ma poi non c'è nulla che impedisca a un cliente di Color di usarlo, magari scambiando i valori in bianco e nero. Inutile dire che ciò causerebbe costernazione per altri clienti della classe Color. La funzione "readonly" affronta questo scenario.

Semplicemente introducendo la parola chiave readonly nelle dichiarazioni, preserviamo l'inizializzazione flessibile evitando al contempo il codice del client.

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red   = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue  = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}

È interessante notare che i membri const sono sempre statici, mentre un membro readonly può essere statico o meno, proprio come un campo normale.

È possibile utilizzare una singola parola chiave per questi due scopi, ma ciò comporta problemi di versioni o problemi di prestazioni. Supponiamo per un momento che abbiamo usato una sola parola chiave per questo (const) e uno sviluppatore ha scritto:

public class A
{
    public static const C = 0;
}

e uno sviluppatore diverso ha scritto un codice basato su A:

public class B
{
    static void Main() => Console.WriteLine(A.C);
}

Ora, il codice generato può basarsi sul fatto che AC è una costante in fase di compilazione? Vale a dire, l'uso di AC può essere semplicemente sostituito dal valore 0? Se dici "sì" a questo, significa che lo sviluppatore di A non può cambiare il modo in cui l'AC viene inizializzato - questo lega le mani allo sviluppatore di A senza permesso.

Se si dice "no" a questa domanda, si perde un'importante ottimizzazione. Forse l'autore di A è positivo sul fatto che AC sarà sempre zero. L'uso di const e readonly consente allo sviluppatore di A di specificare l'intento. Questo rende migliore il comportamento delle versioni e anche le migliori prestazioni.


static readonly se il consumatore è in un assembly diverso. Avere il const e il Consumer in due gruppi diversi è un buon modo per sparare ai piedi .


Const : i valori variabili const devono essere definiti insieme alla dichiarazione e successivamente non cambieranno. const sono implicitamente statici quindi senza creare istanze di classe possiamo accedervi. questo ha un valore in fase di compilazione

ReadOnly : valori delle variabili readonly che possiamo definire dichiarando e utilizzando il costruttore in fase di runtime. le variabili readonly possono accedere senza istanze di classe.

Statico readonly : valori di variabili statiche in sola lettura che possiamo definire dichiarando e solo attraverso il costruttore statico ma non con nessun altro costruttore. Queste variabili sono anche accessibili senza creare istanze di classe (come variabili statiche).

statico di sola lettura sarà una scelta migliore se dovessimo consumare le variabili in diversi gruppi. Si prega di controllare i dettagli completi nel link sottostante

https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/





constants