web-dev-qa-db-fra.com

Statique readonly vs const

J'ai lu des articles sur les champs const et static readonly. Nous avons des classes qui ne contiennent que des valeurs constantes. Utilisé pour diverses choses dans notre système. Je me demande donc si mon observation est correcte:

Ce type de valeurs constantes doit-il toujours être static readonly pour tout ce qui est public? Et n'utilisez que const pour les valeurs internes/protégées/privées?

Que recommandez-vous? Devrais-je peut-être même pas utiliser les champs static readonly, mais plutôt utiliser des propriétés?

1321
Svish

public static readonly les champs sont un peu inhabituels; Les propriétés de public static (avec seulement un get) seraient plus courantes (peut-être sauvegardées par un champ private static readonly).

Les valeurs const sont gravées directement dans le site d’appel; c'est à double tranchant:

  • il est inutile si la valeur est récupérée au moment de l'exécution, peut-être de la configuration
  • si vous changez la valeur d'un const, vous devez reconstruire tous les clients
  • mais cela peut être plus rapide, car cela évite un appel de méthode ...
  • ... qui de temps en temps aurait pu être en ligne

Si la valeur jamais change, alors const va bien - Zero etc., rend des constantes raisonnables; p En dehors de cela, static les propriétés sont plus courantes.

909
Marc Gravell

J'utiliserais static readonly si le consommateur se trouve dans une assemblée différente. Avoir la const et le consommateur dans deux assemblages différents est une bonne façon de se tirer dans le pied .

230
Michael Stum

Peu de choses plus pertinentes à noter:

const int a

  • doit être initialisé.
  • l'initialisation doit être à le temps de compilation .

en lecture seule int a

  • peut utiliser une valeur par défaut, sans initialiser.
  • l'initialisation peut être effectuée à à l'exécution (Édition: dans le constructeur uniquement).
193
Peter

Ceci est juste un complément aux autres réponses. Je ne les répéterai pas (quatre ans plus tard).

Il existe des situations où un const et un non-constent une sémantique différente. Par exemple:

_const int y = 42;

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

affiche True, alors que:

_static readonly int y = 42;

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

écrit False.

La raison en est que la méthode x.Equals a deux surcharges, une qui prend un short (_System.Int16_) et une qui prend un object ( _System.Object_). Maintenant, la question est de savoir si un ou les deux s'appliquent avec mon argument y.

Lorsque y est une constante de compilation (littéral), le cas const, il devient important qu'il existe une conversion implicite frominttoshort à condition que int soit une constante et à condition que le compilateur C # vérifie que sa valeur est comprise dans la plage d'un short (qui _42_ est). Voir Conversions d'expression constante implicites dans la spécification du langage C #. Donc, les deux surcharges doivent être considérées. La surcharge Equals(short) est préférable (toute short est une object, mais toutes les object ne sont pas short). Donc, y est converti en short, et cette surcharge est utilisée. Ensuite, Equals compare deux short de valeur identique, ce qui donne true.

Lorsque y n'est pas une constante, non implicite la conversion de int en short existe. En effet, une int peut être trop énorme pour tenir dans un short. (Une explicite conversion existe, mais je n'ai pas dit Equals((short)y), ce n'est donc pas pertinent.) Nous voyons qu'une seule surcharge s'applique, celle Equals(object). Donc, y est encadré à object. Ensuite, Equals comparera un _System.Int16_ à un _System.Int32_, et puisque les types d'exécution ne sont même pas d'accord, cela donnera false.

Nous concluons que dans certains (rares) cas, le fait de changer un membre de type const en un champ _static readonly_ (ou l’inverse, lorsque cela est possible) peut modifier le comportement du programme.

170
Jeppe Stig Nielsen

Une chose à noter est const est limité aux types primitive/valeur (l'exception étant les chaînes)

87
Chris S

Le mot clé readonly est différent du mot clé const. Un champ const ne peut être initialisé qu'à la déclaration du champ. Un champ readonly peut être initialisé à la déclaration ou dans un constructeur. Par conséquent, les champs readonly peuvent avoir différentes valeurs en fonction du constructeur utilisé. De même, alors qu'un champ const est une constante de compilation, le champ readonly peut être utilisé pour les constantes d'exécution.

Référence MSDN courte et claire ici

25
yazanpro

Static Read Only : la valeur peut être modifiée via le constructeur static au moment de l'exécution. Mais pas à travers la fonction membre.

Constante : Par défaut, static. La valeur ne peut pas être changée de n'importe où (Ctor, Fonction, runtime, etc. no-where).

Lecture seule : la valeur peut être modifiée via le constructeur lors de l'exécution. Mais pas à travers la fonction membre.

Vous pouvez consulter mon rapport: types de propriétés C # .

22
Yeasin Abedin Siam

const et readonly sont similaires, mais ils ne sont pas exactement les mêmes.

Un champ const est une constante au moment de la compilation, ce qui signifie que cette valeur peut être calculée au moment de la compilation. Un champ readonly active des scénarios supplémentaires dans lesquels du code doit être exécuté lors de la construction du type. Après la construction, un champ readonly ne peut plus être modifié.

Par exemple, les membres const peuvent être utilisés pour définir des membres tels que:

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

Comme les valeurs comme 3.14 et 0 sont des constantes à la compilation. Cependant, considérons le cas où vous définissez un type et souhaitez en fournir des instances préfabriquées. Par exemple, vous pouvez définir une classe de couleurs et fournir des "constantes" pour les couleurs courantes telles que Noir, Blanc, etc. Il n'est pas possible de le faire avec des membres const, car les membres de droite ne sont pas des constantes à la compilation. On pourrait faire cela avec des membres statiques réguliers:

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);
}

Mais alors rien n’empêche un client de Color de s’en servir, peut-être en échangeant les valeurs Noir et Blanc. Il va sans dire que cela causerait de la consternation aux autres clients de la classe Color. La fonctionnalité "readonly" répond à ce scénario.

En introduisant simplement le mot-clé readonly dans les déclarations, nous préservons l'initialisation flexible tout en empêchant le code client de s'effondrer.

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);
}

Il est intéressant de noter que les membres const sont toujours statiques, alors qu'un membre en lecture seule peut être statique ou non, comme un champ normal.

Il est possible d'utiliser un seul mot-clé pour ces deux objectifs, mais cela peut entraîner des problèmes de version ou des problèmes de performances. Supposons un instant que nous utilisions un seul mot clé pour cela (const) et qu'un développeur écrivait:

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

et un développeur différent a écrit un code qui s'appuie sur A:

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

Le code généré peut-il maintenant reposer sur le fait que AC est une constante de compilation? C'est-à-dire, l'utilisation de A.C peut-elle simplement être remplacée par la valeur 0? Si vous répondez "oui" à cette question, cela signifie que le développeur de A ne peut pas changer la manière dont A.C est initialisé. Cela lie les mains du développeur de A sans autorisation.

Si vous dites "non" à cette question, une optimisation importante est manquée. L’auteur de A est peut-être convaincu que AC sera toujours égal à zéro. L'utilisation de const et en lecture seule permet au développeur de A de spécifier l'intention. Cela améliore le comportement des versions et les performances.

15
Ramesh Rajendran

Ma préférence est d'utiliser const chaque fois que je le peux, ce qui, comme mentionné ci-dessus, est limité aux expressions littérales ou à quelque chose qui ne nécessite pas d'évaluation.

Si je me méfie de cette limitation, je retombe à en lecture seule statique , avec une mise en garde. J'utiliserais généralement une propriété statique publique avec un getter et un champ de sauvegarde privé statique en lecture seule comme Marc le mentionne ici .

12
Peter Meyer

Const: Const n'est rien d'autre que "constante", une variable dont la valeur est constante mais à la compilation. Et il est obligatoire de lui attribuer une valeur. Par défaut, un const est statique et nous ne pouvons pas changer la valeur d'une variable const dans tout le programme.

ReadOnly statique: La valeur d'une variable de type Readonly statique peut être assignée à l'exécution ou assignée à la compilation et modifiée à l'exécution. Mais la valeur de cette variable ne peut être modifiée que dans le constructeur statique. Et ne peut plus être changé. Cela ne peut changer qu'une fois à l'exécution

Référence: c-sharpcorner

7
mayank

Un champ statique en lecture seule est avantageux pour exposer à d'autres assemblys une valeur susceptible de changer dans une version ultérieure.

Par exemple, supposons que Assembly X expose une constante de la manière suivante:

public const decimal ProgramVersion = 2.3;

Si Assembly Y fait référence à X et utilise cette constante, la valeur 2.3 sera intégrée à Assembly Y lors de la compilation. Cela signifie que si X est ultérieurement recompilé avec la constante définie sur 2.4, Y utilisera toujours l'ancienne valeur de 2.3 jusqu'à ce que Y soit recompilé. Un champ statique en lecture seule évite ce problème.

Une autre façon de voir les choses est que toute valeur susceptible de changer dans le futur n’est pas constante par définition et ne devrait donc pas être représentée comme telle.

6
Yagnesh Cangi

const:

  1. la valeur doit être donnée lors de la déclaration
  2. compiler la constante de temps

lecture seulement:

  1. valeur peut être donnée lors de la déclaration ou pendant l'exécution à l'aide de constructeurs. La valeur peut varier en fonction du constructeur utilisé.
  2. constante de temps d'exécution
3
dasumohan89

Const : les valeurs de la variable const doivent être définies en même temps que la déclaration et ne changeront pas par la suite. const sont implicitement statique, donc sans créer d'instance de classe, nous pouvons y accéder. Ceci a une valeur au moment de la compilation

ReadOnly : valeurs de variable en lecture seule que nous pouvons définir en déclarant ainsi qu'en utilisant le constructeur à l'exécution. les variables en lecture seule ne peuvent pas accéder sans instance de classe.

readonly statique : valeurs de variable static en lecture seule que nous pouvons définir en déclarant aussi bien que par le biais d'un constructeur statique, mais pas avec un autre constructeur. Ces variables sont également accessibles sans créer d'instance de classe (en tant que variables statiques).

statique en lecture seule sera un meilleur choix si nous devons utiliser les variables de différents assemblages. Veuillez vérifier tous les détails dans le lien ci-dessous

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

3
user1756922

Il existe une différence mineure entre les champs const et statiques readonly dans C # .Net

const doit être initialisé avec une valeur lors de la compilation.

const est par défaut statique et doit être initialisé avec une valeur constante, qui ne peut pas être modifiée ultérieurement. Il ne peut pas être utilisé avec tous les types de données. Pour ex-DateTime. Il ne peut pas être utilisé avec le type de données DateTime.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public static readonly string Name = string.Empty; //No error, legal

readonly peut être déclaré statique, mais pas nécessaire. Pas besoin d'initialiser au moment de la déclaration. Sa valeur peut être assignée ou modifiée en utilisant le constructeur une fois. Il est donc possible de changer la valeur du champ en lecture seule une fois (peu importe qu’il soit statique ou non), ce qui n’est pas possible avec const.

2
Chirag

Les constantes sont, comme le nom l’implique, des champs qui ne changent pas et qui sont généralement définis statiquement lors de la compilation dans le code.

Les variables en lecture seule sont des champs qui peuvent changer dans des conditions spécifiques.

Ils peuvent être initialisés lorsque vous les déclarez pour la première fois comme une constante, mais ils le sont généralement lors de la construction d'un objet dans le constructeur.

Ils ne peuvent plus être modifiés après l’initialisation, dans les conditions mentionnées ci-dessus.

La lecture statique seule semble être un mauvais choix pour moi, car si elle est statique et qu'elle ne change jamais, utilisez-la simplement public const. Si elle peut changer, ce n'est pas une constante et ensuite, en fonction de vos besoins, vous pouvez utiliser read -seulement ou juste une variable régulière.

De plus, une autre distinction importante est qu'une constante appartient à la classe, tandis que la variable en lecture seule appartient à l'instance!

0
Claudiu Cojocaru