@donstack, en fait selon la référence C # , un champ en lecture seule peut être affecté et réaffecté plusieurs fois dans la déclaration de champ et le constructeur.
Marques
Réponses:
1289
Outre la différence apparente de
avoir à déclarer la valeur au moment de la définition d'une valeur constVS readonlypeut être calculé dynamiquement mais doit être assigné avant que le constructeur ne quitte .. après cela il est figé.
'const sont implicitement static. Vous utilisez une ClassName.ConstantNamenotation pour y accéder.
Il y a une subtile différence. Considérons une classe définie dans AssemblyA.
AssemblyBréférence AssemblyAet utilise ces valeurs dans le code. Lorsque cela est compilé,
dans le cas de la constvaleur, c'est comme un find-replace, la valeur 2 est «cuite dans» l' AssemblyBIL du. Cela signifie que si demain je mettrai à jour I_CONST_VALUE20 à l'avenir. AssemblyBaurait encore 2 jusqu'à ce que je le recompile .
dans le cas de la readonlyvaleur, c'est comme un refvers un emplacement mémoire. La valeur n'est pas intégrée dans AssemblyBl'IL de. Cela signifie que si l'emplacement mémoire est mis à jour, AssemblyBobtient la nouvelle valeur sans recompilation. Donc, si I_RO_VALUEest mis à jour à 30, il vous suffit de construire AssemblyA. Tous les clients n'ont pas besoin d'être recompilés.
Donc, si vous êtes sûr que la valeur de la constante ne changera pas, utilisez a const.
publicconstint CM_IN_A_METER =100;
Mais si vous avez une constante qui peut changer (précision egwrt) .. ou en cas de doute, utilisez a readonly.
publicreadonlyfloat PI =3.14;
Mise à jour: Aku doit obtenir une mention parce qu'il l'a d'abord signalé. J'ai aussi besoin de brancher où j'ai appris cela .. C # efficace - Bill Wagner
Le staticpoint semble être le point le plus important et le plus utile -consts are implicitly static
LCJ
28
La partie sur les valeurs de référence est la plus importante. Les valeurs const peuvent être optimisées.
CodingBarfield
22
readonlyles variables peuvent être modifiées en dehors du constructeur (réflexion). Ce n'est que le compilateur qui essaie de vous empêcher de modifier la var en dehors du constructeur.
Bitterblue
12
Les readonlyvariables @ mini-me ne peuvent pas être modifiées une fois que le constructeur a terminé, même par réflexion. Le runtime n'arrive pas à appliquer cela. Le runtime n'arrive pas non plus à appliquer ce que vous ne changez string.Emptypas "Hello, world!", mais je ne dirais toujours pas que cela rend string.Emptymodifiable, ou que le code ne devrait pas supposer que ce string.Emptysera toujours une chaîne de longueur nulle.
Il y a un piège avec des consts! Si vous référencez une constante d'un autre assembly, sa valeur sera compilée directement dans l'assembly appelant. De cette façon, lorsque vous mettez à jour la constante dans l'assembly référencé, elle ne change pas dans l'assembly appelant!
Lors de la décompilation (Reflector, ILSpy, ..) une constante JAMAIS JAMAIS est référencée par n'importe qui, peu importe le même assemblage ou un autre assemblage, vous ne pouvez donc pas du tout analyser l'utilisation d'une constante dans le code compilé.
springy76
159
Constantes
Les constantes sont statiques par défaut
Ils doivent avoir une valeur au moment de la compilation (vous pouvez avoir par exemple 3.14 * 2, mais vous ne pouvez pas appeler de méthodes)
Pourrait être déclaré dans les fonctions
Sont copiés dans chaque assembly qui les utilise (chaque assembly obtient une copie locale des valeurs)
Peut être utilisé dans les attributs
Champs d'instance en lecture seule
Doit avoir défini une valeur, au moment où le constructeur quitte
Sont évalués lors de la création de l'instance
Champs statiques en lecture seule
Sont évalués lorsque l'exécution de code atteint la référence de classe (lorsqu'une nouvelle instance est créée ou qu'une méthode statique est exécutée)
Doit avoir une valeur évaluée au moment où le constructeur statique est terminé
Il n'est pas recommandé de mettre ThreadStaticAttribute sur ceux-ci (les constructeurs statiques seront exécutés dans un seul thread et définiront la valeur de son thread; tous les autres threads auront cette valeur non initialisée)
Juste pour ajouter, ReadOnly pour les types de référence ne fait que la référence en lecture seule et non les valeurs. Par exemple:
publicclassConst_V_Readonly{publicconstint I_CONST_VALUE =2;publicreadonlychar[] I_RO_VALUE =newChar[]{'a','b','c'};publicUpdateReadonly(){
I_RO_VALUE[0]='V';//perfectly legal and will update the value
I_RO_VALUE =newchar[]{'V'};//will cause compiler error}}
Existe-t-il un autre type de référence que stringcelui que vous pourriez utiliser comme constante?
springy76
Vous pouvez avoir constdes types de référence autres que chaîne, mais la constante ne peut avoir que la valeur null.
Mike Rosoft
40
Cela explique cela . Résumé: const doit être initialisé au moment de la déclaration, readonly peut être initialisé sur le constructeur (et donc avoir une valeur différente selon le constructeur utilisé).
EDIT: Voir le gotcha de Gishu ci-dessus pour la différence subtile
Il y a un petit gotcha avec lecture seule. Un champ en lecture seule peut être défini plusieurs fois dans le ou les constructeurs. Même si la valeur est définie dans deux constructeurs chaînés différents, elle est toujours autorisée.
publicclassSample{privatereadonlystring ro;publicSample(){
ro ="set";}publicSample(stringvalue):this(){
ro =value;// this works even though it was set in the no-arg ctor}}
Un membre constant est défini au moment de la compilation et ne peut pas être modifié au moment de l'exécution. Les constantes sont déclarées sous forme de champ, à l'aide du constmot clé et doivent être initialisées au fur et à mesure qu'elles sont déclarées.
Un readonlymembre est comme une constante en ce qu'il représente une valeur immuable. La différence est qu'un readonlymembre peut être initialisé au moment de l'exécution, dans un constructeur, tout en pouvant être initialisé lors de leur déclaration.
Ils ne peuvent pas être statiques , ils sont statiques. Vous devriez être clair si vous vouliez dire qu'on ne peut pas déclarerstatic const int i = 0;
nawfal
Pouvez-vous expliquer pourquoi les constdéclarations ne peuvent pas être faites à l'intérieur des méthodes?
Minh Tran
21
Un const est une constante de compilation tandis que la lecture seule permet de calculer une valeur au moment de l'exécution et de la définir dans le constructeur ou l'initialiseur de champ. Ainsi, un «const» est toujours constant, mais «readonly» est en lecture seule une fois qu'il est attribué.
Eric Lippert de l'équipe C # a plus d'informations sur les différents types d'immuabilité
Voici un autre lien montrant comment const n'est pas une version sûre ou pertinente pour les types de référence.
Résumé :
La valeur de votre propriété const est définie au moment de la compilation et ne peut pas changer au moment de l'exécution
Const ne peut pas être marqué comme statique - le mot-clé indique qu'ils sont statiques, contrairement aux champs en lecture seule qui le peuvent.
Const ne peut pas être autre chose que des types de valeur (primitifs)
Le mot clé en lecture seule marque le champ comme immuable. Cependant, la propriété peut être modifiée à l'intérieur du constructeur de la classe
Le mot clé en lecture seule peut également être combiné avec statique pour le faire agir de la même manière qu'un const (au moins en surface). Il y a une différence marquée quand on regarde l'IL entre les deux
les champs const sont marqués comme "littéraux" en IL tandis que readonly est "initonly"
Je crois qu'une constvaleur est la même pour tous les objets (et doit être initialisée avec une expression littérale), alors qu'elle readonlypeut être différente pour chaque instanciation ...
L'un des membres de l'équipe de notre bureau a fourni les conseils suivants sur le moment d'utiliser const, static et readonly:
Utilisez const lorsque vous avez une variable d'un type que vous pouvez savoir au moment de l'exécution (littéral de chaîne, entier, double, énumérations, ...) que vous voulez que toutes les instances ou les consommateurs d'une classe aient accès à l'endroit où la valeur ne doit pas changer.
Utilisez statique lorsque vous disposez de données pour que toutes les instances ou tous les consommateurs d'une classe aient accès à l'endroit où la valeur peut changer.
Utilisez statique en lecture seule lorsque vous avez une variable d'un type que vous ne pouvez pas savoir au moment de l'exécution (objets) que vous souhaitez que toutes les instances ou les consommateurs d'une classe aient accès à l'endroit où la valeur ne doit pas changer.
Utilisez en lecture seule lorsque vous avez une variable de niveau d'instance que vous saurez au moment de la création d'objet qui ne devrait pas changer.
Une dernière remarque: un champ const est statique, mais l'inverse n'est pas vrai.
Je pense que vous voulez dire «converser». L'inverse serait "un champ non const n'est pas statique". Ce qui peut être vrai ou non. L'inverse, "un champ statique est (toujours) const" n'est pas vrai.
Michael Blackburn
5
Ils sont tous les deux constants, mais un const est également disponible au moment de la compilation. Cela signifie qu'un aspect de la différence est que vous pouvez utiliser des variables const comme entrée pour attribuer des constructeurs, mais pas des variables en lecture seule.
Exemple:
publicstaticclassText{publicconststringConstDescription="This can be used.";publicreadonlystaticstringReadonlyDescription="Cannot be used.";}publicclassFoo{[Description(Text.ConstDescription)]publicintBarThatBuilds{{get;set;}}[Description(Text.ReadOnlyDescription)]publicintBarThatDoesNotBuild{{get;set;}}}
constante de compilation : constante absolue , la valeur est définie lors de la déclaration, se trouve dans le code IL lui-même
readonly
constante d' exécution : peut être définie dans le constructeur / init via le fichier de configuration, c'est App.config-à- dire , mais une fois initialisée, elle ne peut pas être modifiée
Les variables marquées const sont un peu plus que des macros #define fortement typées, au moment de la compilation, les références des variables const sont remplacées par des valeurs littérales en ligne. Par conséquent, seuls certains types de valeurs primitifs intégrés peuvent être utilisés de cette manière. Les variables marquées en lecture seule peuvent être définies, dans un constructeur, au moment de l'exécution et leur lecture seule est également appliquée lors de l'exécution. Il y a un coût de performance mineur associé à cela, mais cela signifie que vous pouvez utiliser en lecture seule avec n'importe quel type (même les types de référence).
En outre, les variables const sont intrinsèquement statiques, tandis que les variables en lecture seule peuvent être spécifiques à l'instance si vous le souhaitez.
Ajout que les consts sont des macros #define fortement typées . Sinon, nous pouvons effrayer toutes les personnes C ou C ++. :-)
Jason Baker
4
CONST
Le mot clé const peut être appliqué aux champs ou aux variables locales
Nous devons attribuer un champ const au moment de la déclaration
Aucune mémoire allouée car la valeur const est incorporée dans le code IL lui-même après la compilation. C'est comme trouver toutes les occurrences de la variable const et remplacer par sa valeur. Ainsi, le code IL après la compilation aura des valeurs codées en dur à la place des variables const
Les const en C # sont par défaut statiques.
La valeur est constante pour tous les objets
Il existe un problème de version de DLL - Cela signifie que chaque fois que nous modifions une variable ou une propriété const publique ((en fait, elle n'est pas censée être modifiée théoriquement)), toute autre DLL ou assemblage qui utilise cette variable doit être reconstruite.
Seuls les types intégrés C # peuvent être déclarés constants
Le champ const ne peut pas être transmis comme paramètre ref ou out
Lecture seulement
le mot clé en lecture seule s'applique uniquement aux champs et non aux variables locales
Nous pouvons attribuer un champ en lecture seule au moment de la déclaration ou dans le constructeur, pas dans d'autres méthodes.
mémoire dynamique allouée aux champs en lecture seule et nous pouvons obtenir la valeur au moment de l'exécution.
En lecture seule appartient à l'objet créé, donc accessible via une seule instance de classe. Pour le rendre membre de la classe, nous devons ajouter un mot clé statique avant la lecture seule.
La valeur peut être différente selon le constructeur utilisé (car elle appartient à l'objet de la classe)
Si vous déclarez un type non primitif (type référence) en lecture seule, seule la référence est immuable et non l'objet qu'il contient.
Étant donné que la valeur est obtenue au moment de l'exécution, il n'y a pas de problème de version de DLL avec les champs / propriétés en lecture seule.
Nous pouvons passer le champ en lecture seule en tant que paramètres ref ou out dans le contexte du constructeur.
Puisque const ne fonctionne vraiment qu'avec les types de données de base, si vous voulez travailler avec une classe, vous pouvez vous sentir "obligé" d'utiliser ReadOnly. Attention cependant au piège! ReadOnly signifie que vous ne pouvez pas remplacer l'objet par un autre objet (vous ne pouvez pas le faire référence à un autre objet). Mais tout processus qui a une référence à l'objet est libre de modifier les valeurs à l' intérieur de l'objet!
Ne soyez donc pas confus en pensant que ReadOnly implique qu'un utilisateur ne peut pas changer les choses. Il n'y a pas de syntaxe simple en C # pour empêcher une instanciation d'une classe de voir ses valeurs internes modifiées (pour autant que je sache).
Oui, c'est plus un thème général. Si vous disposez d'une propriété get only exposant une liste, vous pouvez toujours modifier la liste. Vous ne pouvez pas définir une liste d'array différente pour cette propriété, mais vous ne pouvez pas empêcher l'utilisateur de modifier la liste d'array.
Gishu
3
A constdoit être codé en dur , où as readonlypeut être défini dans le constructeur de la classe.
Il existe une différence notable entre les champs const et readonly dans C # .Net
const est par défaut statique et doit être initialisé avec une valeur constante, qui ne peut pas être modifiée ultérieurement. Le changement de valeur n'est pas non plus autorisé dans les constructeurs. Il ne peut pas être utilisé avec tous les types de données. Par exemple DateTime. Il ne peut pas être utilisé avec le type de données DateTime.
readonly peut être déclaré comme statique, mais pas nécessaire. Pas besoin d'initialiser au moment de la déclaration. Sa valeur peut être affectée ou modifiée à l'aide du constructeur. Ainsi, il donne un avantage lorsqu'il est utilisé comme membre de classe d'instance. Deux instanciations différentes peuvent avoir une valeur différente de champ en lecture seule. Par exemple -
class A
{publicreadonlyintId;public A(int i){Id= i;}}
Ensuite, le champ en lecture seule peut être initialisé avec des valeurs spécifiques instantanées, comme suit:
A objOne =new A(5);
A objTwo =new A(10);
Ici, instance objOne aura la valeur du champ en lecture seule comme 5 et objTwo en a 10. Ce qui n'est pas possible en utilisant const.
Une constante sera compilée dans le consommateur en tant que valeur littérale tandis que la chaîne statique servira de référence à la valeur définie.
En tant qu'exercice, essayez de créer une bibliothèque externe et de la consommer dans une application console, puis modifiez les valeurs dans la bibliothèque et recompilez-la (sans recompiler le programme consommateur), déposez la DLL dans le répertoire et exécutez EXE manuellement, vous devriez trouver que la chaîne constante ne change pas.
@Andrew Hare - oui, je viens de vérifier. Je suis très surpris, c'est un vrai piège, je suis vraiment très surpris par ça, étonné que ce soit le cas ...!
ljs
Je m'oppose toutefois à l'utilisation du mot pointeur ici. Ce n'est pas un pointeur, c'est une référence, et il y a une différence en C # car vous pouvez manipuler des pointeurs non gérés en mode non sécurisé, il est donc important de faire la distinction entre les deux.
ljs
2
Constant
Nous devons fournir la valeur au champ const lorsqu'il est défini. Le compilateur enregistre ensuite la valeur de la constante dans les métadonnées de l'assembly. Cela signifie qu'une constante ne peut être définie que pour le type primitif comme booléen, char, octet, etc. Les constantes sont toujours considérées comme des membres statiques et non comme des membres d'instance.
Lecture seulement
Les champs en lecture seule ne peuvent être résolus qu'au moment de l'exécution. Cela signifie que nous pouvons définir une valeur pour une valeur en utilisant le constructeur pour le type dans lequel le champ est déclaré. La vérification est effectuée par le compilateur que les champs en lecture seule ne sont pas écrits par une méthode autre que le constructeur.
Principalement; vous pouvez attribuer une valeur à un champ en lecture seule statique à une valeur non constante au moment de l'exécution, tandis qu'un const doit recevoir une valeur constante.
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 en lecture seule permet 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 en lecture seule ne peut pas être modifié.
Par exemple, les membres const peuvent être utilisés pour définir des membres comme:
puisque 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 des instances préfabriquées. Par exemple, vous souhaiterez peut-être définir une classe Color et fournir des "constantes" pour les couleurs courantes comme le noir, le blanc, etc. On pourrait le faire avec des membres statiques réguliers:
publicclassColor{publicstaticColorBlack=newColor(0,0,0);publicstaticColorWhite=newColor(255,255,255);publicstaticColorRed=newColor(255,0,0);publicstaticColorGreen=newColor(0,255,0);publicstaticColorBlue=newColor(0,0,255);privatebyte red, green, blue;publicColor(byte r,byte g,byte b){
red = r;
green = g;
blue = b;}}
mais alors il n'y a rien pour empêcher un client de Color de s'en occuper, peut-être en échangeant les valeurs Noir et Blanc. Inutile de dire que cela provoquerait la consternation pour les autres clients de la classe Color. La fonctionnalité "en lecture seule" résout ce scénario. En introduisant simplement le mot-clé en lecture seule dans les déclarations, nous préservons l'initialisation flexible tout en empêchant le code client de contourner.
publicclassColor{publicstaticreadonlyColorBlack=newColor(0,0,0);publicstaticreadonlyColorWhite=newColor(255,255,255);publicstaticreadonlyColorRed=newColor(255,0,0);publicstaticreadonlyColorGreen=newColor(0,255,0);publicstaticreadonlyColorBlue=newColor(0,0,255);privatebyte red, green, blue;publicColor(byte r,byte g,byte b){
red = r;
green = g;
blue = 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, tout comme un champ normal.
Il est possible d'utiliser un seul mot-clé à ces deux fins, mais cela entraîne des problèmes de version ou des problèmes de performances. Supposons un instant que nous ayons utilisé un seul mot-clé pour cela (const) et un développeur a écrit:
publicclass A
{publicstaticconst C =0;}
et un développeur différent a écrit du code qui s'appuyait sur A:
publicclass B
{staticvoidMain(){Console.WriteLine(A.C);}}
Maintenant, le code généré peut-il s'appuyer sur le fait que AC est une constante de temps de compilation? C'est-à-dire, l'utilisation de AC peut-elle simplement être remplacée par la valeur 0? Si vous dites «oui» à cela, cela signifie que le développeur de A ne peut pas changer la façon dont AC 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 certain que AC sera toujours nul. L'utilisation de const et readonly permet au développeur de A de spécifier l'intention. Cela permet un meilleur comportement de version et également de meilleures performances.
ReadOnly: La valeur ne sera initialisée qu'une seule fois à partir du constructeur de la classe.
const: peut être initialisé dans n'importe quelle fonction mais une seule fois
La différence est que la valeur d'un champ en lecture seule statique est définie au moment de l'exécution, de sorte qu'il peut avoir une valeur différente pour différentes exécutions du programme. Cependant, la valeur d'un champ const est définie sur une constante de temps de compilation.
N'oubliez pas: pour les types de référence, dans les deux cas (statique et instance), le modificateur en lecture seule vous empêche uniquement d'attribuer une nouvelle référence au champ. Elle ne rend pas spécifiquement immuable l'objet visé par la référence.
Les variables constantes sont déclarées et initialisées au moment de la compilation. La valeur ne peut pas être modifiée après les quartiers. Les variables en lecture seule seront initialisées uniquement à partir du constructeur statique de la classe. La lecture seule est utilisée uniquement lorsque nous voulons affecter la valeur au moment de l'exécution.
Votre définition de "Readonly" qu'il peut changer est erronée. Je suppose que par «changer», vous vouliez dire «définir», comme «il peut être défini au moment de l'exécution».
Ahmed
0
Une chose à ajouter à ce que les gens ont dit ci-dessus. Si vous avez un assembly contenant une valeur en lecture seule (par exemple, readonly MaxFooCount = 4;), vous pouvez modifier la valeur que les assemblys appelants voient en expédiant une nouvelle version de cet assembly avec une valeur différente (par exemple readonly MaxFooCount = 5;)
Mais avec un const, il serait intégré au code de l'appelant lors de la compilation de l'appelant.
Si vous avez atteint ce niveau de compétence C #, vous êtes prêt pour le livre de Bill Wagner, Effective C #: 50 façons spécifiques d'améliorer votre C #, qui répond à cette question en détail (et 49 autres choses).
Réponses:
Outre la différence apparente de
const
VSreadonly
peut être calculé dynamiquement mais doit être assigné avant que le constructeur ne quitte .. après cela il est figé.static
. Vous utilisez uneClassName.ConstantName
notation pour y accéder.Il y a une subtile différence. Considérons une classe définie dans
AssemblyA
.AssemblyB
référenceAssemblyA
et utilise ces valeurs dans le code. Lorsque cela est compilé,const
valeur, c'est comme un find-replace, la valeur 2 est «cuite dans» l'AssemblyB
IL du. Cela signifie que si demain je mettrai à jourI_CONST_VALUE
20 à l'avenir.AssemblyB
aurait encore 2 jusqu'à ce que je le recompile .readonly
valeur, c'est comme unref
vers un emplacement mémoire. La valeur n'est pas intégrée dansAssemblyB
l'IL de. Cela signifie que si l'emplacement mémoire est mis à jour,AssemblyB
obtient la nouvelle valeur sans recompilation. Donc, siI_RO_VALUE
est mis à jour à 30, il vous suffit de construireAssemblyA
. Tous les clients n'ont pas besoin d'être recompilés.Donc, si vous êtes sûr que la valeur de la constante ne changera pas, utilisez a
const
.Mais si vous avez une constante qui peut changer (précision egwrt) .. ou en cas de doute, utilisez a
readonly
.Mise à jour: Aku doit obtenir une mention parce qu'il l'a d'abord signalé. J'ai aussi besoin de brancher où j'ai appris cela .. C # efficace - Bill Wagner
la source
static
point semble être le point le plus important et le plus utile -consts are implicitly static
readonly
les variables peuvent être modifiées en dehors du constructeur (réflexion). Ce n'est que le compilateur qui essaie de vous empêcher de modifier la var en dehors du constructeur.readonly
variables @ mini-me ne peuvent pas être modifiées une fois que le constructeur a terminé, même par réflexion. Le runtime n'arrive pas à appliquer cela. Le runtime n'arrive pas non plus à appliquer ce que vous ne changezstring.Empty
pas"Hello, world!"
, mais je ne dirais toujours pas que cela rendstring.Empty
modifiable, ou que le code ne devrait pas supposer que cestring.Empty
sera toujours une chaîne de longueur nulle.Il y a un piège avec des consts! Si vous référencez une constante d'un autre assembly, sa valeur sera compilée directement dans l'assembly appelant. De cette façon, lorsque vous mettez à jour la constante dans l'assembly référencé, elle ne change pas dans l'assembly appelant!
la source
Constantes
Champs d'instance en lecture seule
Champs statiques en lecture seule
la source
Juste pour ajouter, ReadOnly pour les types de référence ne fait que la référence en lecture seule et non les valeurs. Par exemple:
la source
string
celui que vous pourriez utiliser comme constante?const
des types de référence autres que chaîne, mais la constante ne peut avoir que la valeurnull
.Cela explique cela . Résumé: const doit être initialisé au moment de la déclaration, readonly peut être initialisé sur le constructeur (et donc avoir une valeur différente selon le constructeur utilisé).
EDIT: Voir le gotcha de Gishu ci-dessus pour la différence subtile
la source
const
: Ne peut être changé nulle part.readonly
: Cette valeur ne peut être modifiée que dans le constructeur. Ne peut pas être modifié dans les fonctions normales.la source
Il y a un petit gotcha avec lecture seule. Un champ en lecture seule peut être défini plusieurs fois dans le ou les constructeurs. Même si la valeur est définie dans deux constructeurs chaînés différents, elle est toujours autorisée.
la source
Un membre constant est défini au moment de la compilation et ne peut pas être modifié au moment de l'exécution. Les constantes sont déclarées sous forme de champ, à l'aide du
const
mot clé et doivent être initialisées au fur et à mesure qu'elles sont déclarées.Un
readonly
membre est comme une constante en ce qu'il représente une valeur immuable. La différence est qu'unreadonly
membre peut être initialisé au moment de l'exécution, dans un constructeur, tout en pouvant être initialisé lors de leur déclaration.const
static
(ils sont implicitement statiques)lecture seulement
la source
static const int i = 0;
const
déclarations ne peuvent pas être faites à l'intérieur des méthodes?Un const est une constante de compilation tandis que la lecture seule permet de calculer une valeur au moment de l'exécution et de la définir dans le constructeur ou l'initialiseur de champ. Ainsi, un «const» est toujours constant, mais «readonly» est en lecture seule une fois qu'il est attribué.
Eric Lippert de l'équipe C # a plus d'informations sur les différents types d'immuabilité
la source
Voici un autre lien montrant comment const n'est pas une version sûre ou pertinente pour les types de référence.
Résumé :
la source
Lecture seule : la valeur peut être modifiée via Ctor lors de l'exécution. Mais pas via la fonction membre
Constante : par défaut statique. La valeur ne peut pas être modifiée de n'importe où (Ctor, Function, runtime etc no-where)
la source
Encore un autre problème: les valeurs en lecture seule peuvent être modifiées par du code "sournois" via la réflexion.
Puis-je modifier un champ hérité en lecture seule privé en C # en utilisant la réflexion?
la source
Je crois qu'une
const
valeur est la même pour tous les objets (et doit être initialisée avec une expression littérale), alors qu'ellereadonly
peut être différente pour chaque instanciation ...la source
L'un des membres de l'équipe de notre bureau a fourni les conseils suivants sur le moment d'utiliser const, static et readonly:
Une dernière remarque: un champ const est statique, mais l'inverse n'est pas vrai.
la source
Ils sont tous les deux constants, mais un const est également disponible au moment de la compilation. Cela signifie qu'un aspect de la différence est que vous pouvez utiliser des variables const comme entrée pour attribuer des constructeurs, mais pas des variables en lecture seule.
Exemple:
la source
quand utiliser
const
oureadonly
const
readonly
App.config
-à- dire , mais une fois initialisée, elle ne peut pas être modifiéela source
Les variables marquées const sont un peu plus que des macros #define fortement typées, au moment de la compilation, les références des variables const sont remplacées par des valeurs littérales en ligne. Par conséquent, seuls certains types de valeurs primitifs intégrés peuvent être utilisés de cette manière. Les variables marquées en lecture seule peuvent être définies, dans un constructeur, au moment de l'exécution et leur lecture seule est également appliquée lors de l'exécution. Il y a un coût de performance mineur associé à cela, mais cela signifie que vous pouvez utiliser en lecture seule avec n'importe quel type (même les types de référence).
En outre, les variables const sont intrinsèquement statiques, tandis que les variables en lecture seule peuvent être spécifiques à l'instance si vous le souhaitez.
la source
CONST
Lecture seulement
la source
Un autre gotcha .
Puisque const ne fonctionne vraiment qu'avec les types de données de base, si vous voulez travailler avec une classe, vous pouvez vous sentir "obligé" d'utiliser ReadOnly. Attention cependant au piège! ReadOnly signifie que vous ne pouvez pas remplacer l'objet par un autre objet (vous ne pouvez pas le faire référence à un autre objet). Mais tout processus qui a une référence à l'objet est libre de modifier les valeurs à l' intérieur de l'objet!
Ne soyez donc pas confus en pensant que ReadOnly implique qu'un utilisateur ne peut pas changer les choses. Il n'y a pas de syntaxe simple en C # pour empêcher une instanciation d'une classe de voir ses valeurs internes modifiées (pour autant que je sache).
la source
A
const
doit être codé en dur , où asreadonly
peut être défini dans le constructeur de la classe.la source
Il existe une différence notable entre les champs const et readonly dans C # .Net
const est par défaut statique et doit être initialisé avec une valeur constante, qui ne peut pas être modifiée ultérieurement. Le changement de valeur n'est pas non plus autorisé dans les constructeurs. Il ne peut pas être utilisé avec tous les types de données. Par exemple DateTime. Il ne peut pas être utilisé avec le type de données DateTime.
readonly peut être déclaré comme statique, mais pas nécessaire. Pas besoin d'initialiser au moment de la déclaration. Sa valeur peut être affectée ou modifiée à l'aide du constructeur. Ainsi, il donne un avantage lorsqu'il est utilisé comme membre de classe d'instance. Deux instanciations différentes peuvent avoir une valeur différente de champ en lecture seule. Par exemple -
Ensuite, le champ en lecture seule peut être initialisé avec des valeurs spécifiques instantanées, comme suit:
Ici, instance objOne aura la valeur du champ en lecture seule comme 5 et objTwo en a 10. Ce qui n'est pas possible en utilisant const.
la source
Une constante sera compilée dans le consommateur en tant que valeur littérale tandis que la chaîne statique servira de référence à la valeur définie.
En tant qu'exercice, essayez de créer une bibliothèque externe et de la consommer dans une application console, puis modifiez les valeurs dans la bibliothèque et recompilez-la (sans recompiler le programme consommateur), déposez la DLL dans le répertoire et exécutez EXE manuellement, vous devriez trouver que la chaîne constante ne change pas.
la source
Constant
Nous devons fournir la valeur au champ const lorsqu'il est défini. Le compilateur enregistre ensuite la valeur de la constante dans les métadonnées de l'assembly. Cela signifie qu'une constante ne peut être définie que pour le type primitif comme booléen, char, octet, etc. Les constantes sont toujours considérées comme des membres statiques et non comme des membres d'instance.
Lecture seulement
Les champs en lecture seule ne peuvent être résolus qu'au moment de l'exécution. Cela signifie que nous pouvons définir une valeur pour une valeur en utilisant le constructeur pour le type dans lequel le champ est déclaré. La vérification est effectuée par le compilateur que les champs en lecture seule ne sont pas écrits par une méthode autre que le constructeur.
Plus sur les deux expliqués ici dans cet article
la source
Principalement; vous pouvez attribuer une valeur à un champ en lecture seule statique à une valeur non constante au moment de l'exécution, tandis qu'un const doit recevoir une valeur constante.
la source
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 en lecture seule permet 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 en lecture seule ne peut pas être modifié.
Par exemple, les membres const peuvent être utilisés pour définir des membres comme:
puisque 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 des instances préfabriquées. Par exemple, vous souhaiterez peut-être définir une classe Color et fournir des "constantes" pour les couleurs courantes comme le noir, le blanc, etc. On pourrait le faire avec des membres statiques réguliers:
mais alors il n'y a rien pour empêcher un client de Color de s'en occuper, peut-être en échangeant les valeurs Noir et Blanc. Inutile de dire que cela provoquerait la consternation pour les autres clients de la classe Color. La fonctionnalité "en lecture seule" résout ce scénario. En introduisant simplement le mot-clé en lecture seule dans les déclarations, nous préservons l'initialisation flexible tout en empêchant le code client de contourner.
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, tout comme un champ normal.
Il est possible d'utiliser un seul mot-clé à ces deux fins, mais cela entraîne des problèmes de version ou des problèmes de performances. Supposons un instant que nous ayons utilisé un seul mot-clé pour cela (const) et un développeur a écrit:
et un développeur différent a écrit du code qui s'appuyait sur A:
Maintenant, le code généré peut-il s'appuyer sur le fait que AC est une constante de temps de compilation? C'est-à-dire, l'utilisation de AC peut-elle simplement être remplacée par la valeur 0? Si vous dites «oui» à cela, cela signifie que le développeur de A ne peut pas changer la façon dont AC 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 certain que AC sera toujours nul. L'utilisation de const et readonly permet au développeur de A de spécifier l'intention. Cela permet un meilleur comportement de version et également de meilleures performances.
la source
ReadOnly: La valeur ne sera initialisée qu'une seule fois à partir du constructeur de la classe.
const: peut être initialisé dans n'importe quelle fonction mais une seule fois
la source
La différence est que la valeur d'un champ en lecture seule statique est définie au moment de l'exécution, de sorte qu'il peut avoir une valeur différente pour différentes exécutions du programme. Cependant, la valeur d'un champ const est définie sur une constante de temps de compilation.
N'oubliez pas: pour les types de référence, dans les deux cas (statique et instance), le modificateur en lecture seule vous empêche uniquement d'attribuer une nouvelle référence au champ. Elle ne rend pas spécifiquement immuable l'objet visé par la référence.
Pour plus de détails, veuillez consulter la foire aux questions C # sur ce sujet: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
la source
Les variables constantes sont déclarées et initialisées au moment de la compilation. La valeur ne peut pas être modifiée après les quartiers. Les variables en lecture seule seront initialisées uniquement à partir du constructeur statique de la classe. La lecture seule est utilisée uniquement lorsque nous voulons affecter la valeur au moment de l'exécution.
la source
Const : valeur constante absolue pendant la durée de vie de l'application.
Lecture seule : il peut être modifié en temps d'exécution.
la source
Une chose à ajouter à ce que les gens ont dit ci-dessus. Si vous avez un assembly contenant une valeur en lecture seule (par exemple, readonly MaxFooCount = 4;), vous pouvez modifier la valeur que les assemblys appelants voient en expédiant une nouvelle version de cet assembly avec une valeur différente (par exemple readonly MaxFooCount = 5;)
Mais avec un const, il serait intégré au code de l'appelant lors de la compilation de l'appelant.
Si vous avez atteint ce niveau de compétence C #, vous êtes prêt pour le livre de Bill Wagner, Effective C #: 50 façons spécifiques d'améliorer votre C #, qui répond à cette question en détail (et 49 autres choses).
la source