Question Statique readonly vs const


J'ai lu à propos de const et static readonly des champs. Nous avons quelques classes qui ne contiennent que des valeurs constantes. Utilisé pour diverses choses dans notre système. Donc je me demande si mon observation est correcte:

Est-ce que ce genre de valeurs constantes doit toujours être static readonly pour tout ce qui est public? Et seulement utiliser const pour les valeurs internes / protégées / privées?

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


1201
2018-04-16 11:21


origine


Réponses:


public static readonly les champs sont un peu inhabituels; public static propriétés (avec seulement get) serait plus commun (peut-être soutenu par un private static readonly champ).

const les valeurs sont brûlées directement dans le site d'appel; c'est double tranchant:

  • il est inutile si la valeur est récupérée à l'exécution, peut-être à partir de la configuration
  • si vous changez la valeur d'un const, vous devez reconstruire tous les clients
  • mais ça peut être plus rapide, car cela évite un appel de méthode ...
  • ... qui peut parfois avoir été inline par le JIT de toute façon

Si la valeur sera jamais changer, alors const est bien - Zero etc faire des consts raisonnables; p Autre que cela, static les propriétés sont plus communes.


828
2018-04-16 11:24



j'utiliserais static readonly si la Consommateur est dans un assemblage différent. Avoir le const et le Consommateur dans deux assemblées différentes est un bon moyen de Tirez-vous dans le pied.


199
2018-04-16 12:57



Quelques autres choses

const int a 

  • doit être initialisé
  • l'initialisation doit être au moment de la compilation

readonly int un

  • peut utiliser la valeur par défaut, sans initialiser
  • l'initialisation peut être au moment de l'exécution

173
2018-04-16 11:36



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

Il y a des situations où un const et un non-const ont des sémantiques différentes. Par exemple:

const int y = 42;

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

imprime True, tandis 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 dans un short (System.Int16) et celui qui prend un object (System.Object). Maintenant, la question est de savoir si l'un ou les deux s'appliquent avec mon y argument.

Quand y est une constante à la compilation (littérale), la const cas, il devient important qu'il existe une conversion implicite de  int  à  short à condition que int est une constante, et à condition que le compilateur C # vérifie que sa valeur est dans la plage d'un short (lequel 42 est). Voir Conversions d'expressions constantes implicites dans la spécification de langage C #. Donc les deux surcharges doivent être considérées. La surcharge Equals(short) est préféré (tout short est un object, mais pas tout object sont short). Alors y est converti en shortet cette surcharge est utilisée. alors Equals compare deux short de valeur identique, et cela donne true.

Quand y n'est pas une constante, non implicite conversion de int à short existe. C'est parce qu'en général un intpeut être trop grand pour entrer dans un short. (Un explicite la conversion existe, mais je n'ai pas dit Equals((short)y), donc ce n'est pas pertinent.) Nous voyons qu'une seule surcharge s'applique, la Equals(object) un. Alors y est encadré à object. alors Equals va comparer 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 cas (rares), const type membre à un static readonly champ (ou dans l'autre sens, lorsque cela est possible) peut changer le comportement du programme.


151
2017-09-11 14:52



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


82
2018-04-16 11:28



le readonly mot-clé est différent de la const mot-clé. UNE const Le champ ne peut être initialisé qu'à la déclaration du champ. UNE readonly champ peut être initialisé soit à la déclaration, soit dans un constructeur. Donc, readonly les champs peuvent avoir des valeurs différentes selon le constructeur utilisé. En outre, alors qu'un const champ est une constante de compilation, le readonly champ peut être utilisé pour les constantes d'exécution

Référence MSDN courte et claire ici


23
2017-11-14 18:58



Lecture statique uniquement : La valeur peut être changée à travers static constructeur à l'exécution. Mais pas à travers la fonction membre.

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

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

Vous pouvez jeter un oeil à mon repo: Types de propriété C #.


16
2018-01-12 17:14



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

UNE const field est une constante à la compilation, ce qui signifie que cette valeur peut être calculée à la compilation. UNE readonly Ce champ active des scénarios supplémentaires dans lesquels du code doit être exécuté pendant la construction du type. Après la construction, un readonly le champ ne peut pas être changé.

Par exemple, const Les membres peuvent être utilisés pour définir des membres comme:

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

Depuis les valeurs comme 3.14 et 0 sont des constantes de compilation. Cependant, considérez le cas où vous définissez un type et souhaitez en fournir quelques exemples. Par exemple, vous pourriez vouloir définir une classe Color et fournir des "constantes" pour des couleurs communes comme Black, White, etc. Il n'est pas possible de faire cela avec les membres const, car les cotés droits ne sont pas des constantes de compilation. On pourrait le faire 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, il n'y a rien pour empêcher un client de Color de le faire, peut-être en échangeant les valeurs en noir et blanc. Inutile de dire que cela causerait de la consternation pour les autres clients de la classe Color. La fonctionnalité "en lecture seule" traite ce scénario.

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

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, tandis qu'un membre readonly peut être statique ou non, tout comme un champ normal.

Il est possible d'utiliser un seul mot clé pour ces deux objectifs, mais cela entraîne des problèmes de version ou de performances. Supposons un instant que nous avons utilisé un seul mot-clé pour ce (const) et un développeur a écrit:

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

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

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

Maintenant, le code généré peut-il s'appuyer sur le fait que A.C est une constante de compilation? Par exemple, l'utilisation de A.C peut-elle simplement être remplacée par la valeur 0? Si vous dites "oui" à ceci, alors cela signifie que le développeur de A ne peut pas changer la façon dont A.C est initialisé - ceci lie les mains du développeur de A sans permission.

Si vous dites "non" à cette question, une optimisation importante est manquée. L'auteur de A est peut-être positif que A.C sera toujours nul. L'utilisation de const et de readonly permet au développeur de A de spécifier l'intention. Cela améliore le comportement de gestion des versions et améliore les performances.


13
2017-09-28 08:19



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

Si je me réchauffe contre cette limitation, alors je me replie sur lecture statique, avec une mise en garde. J'utiliserais généralement une propriété statique publique avec un getter et un support readonly statique privé champ comme Marc mentionne ici.


11
2018-04-16 12:48



Un champ de lecture statique est avantageux lors de l'exposition à autres assemblages une valeur qui pourrait changer dans une version ultérieure.

Par exemple, supposons un assemblage X expose une constante comme suit:

public const decimal ProgramVersion = 2.3;

Si l'assemblage Y les références X et utilise cette constante, la valeur 2,3 sera cuit dans l'assemblage Y lorsqu'il est compilé. Cela signifie que si X est recompilée plus tard avec la constante définie sur 2.4, Y sera toujours utiliser l'ancienne valeur de 2,3 jusqu'à Y est recompilé. Un statique Le champ readonly évite ce problème.

Une autre façon de voir cela est que toute valeur qui pourrait changement dans le futur n'est pas constant par définition, et devrait donc ne pas être représenté comme un.


6
2018-04-07 13:44



Const: Const n'est rien d'autre que "constant", 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 tout au long du programme.

Statique en lecture seule: Une valeur de variable de type Static Readonly peut être affectée lors de l'exécution ou affectée lors de la compilation et modifiée lors de l'exécution. Mais la valeur de cette variable ne peut être modifiée que dans le constructeur statique. Et ne peut pas être changé plus loin. Il ne peut changer qu'une seule fois à l'exécution

Référence: c-sharpcorner


5
2017-09-09 07:16