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?
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:
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.
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 .
const int a
en lecture seule int a
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 fromint
toshort
à 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.
Une chose à noter est const est limité aux types primitive/valeur (l'exception étant les chaînes)
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.
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 # .
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.
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 .
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
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.
const:
lecture seulement:
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/
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.
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!