property - static const c#




Quelle est la différence entre const et readonly? (20)

Quelle est la différence entre const et readonly et utilisez-vous l'un par rapport à l'autre?


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 ne peuvent pas appeler les 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

En lecture seule les champs d'instance

  • Doit avoir une valeur définie, 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 du code atteint la référence de la 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é d'y ajouter ThreadStaticAttribute (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)

Const et readonly sont similaires, mais ils ne sont pas exactement les mêmes. Un champ const est une constante à 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é pendant 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:

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

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 quelques exemples. Par exemple, vous pouvez définir une classe Color et fournir des "constantes" pour les couleurs courantes comme Noir, Blanc, etc. Il n'est pas possible de faire cela avec les membres const, car les côté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 = r;
        green = g;
        blue = b;
    }
}

mais alors il n'y a rien pour empêcher un client de Color de le faire, peut-être en échangeant les valeurs Black et White. 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 mot clé readonly 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 = r;
        green = g;
        blue = b;
    }
}

Il est intéressant de noter que les membres const sont toujours statiques, tandis 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é 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 AC est une constante de compilation? Autrement dit, l'utilisation de AC peut-elle simplement être remplacée par la valeur 0? Si vous dites "oui" à ceci, cela signifie que le développeur de A ne peut pas changer la façon dont AC 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. Peut-être que l'auteur de A est positif que AC sera toujours zéro. 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.



Il y a un gotcha avec 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 changera pas dans l'assembly appelant!


Il y a 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 plus tard. Le changement de valeur n'est pas autorisé dans les constructeurs aussi. 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 readonly string Name = string.Empty; //No error, legal

readonly peut être déclaré statique, mais pas nécessaire. Pas besoin de s'initialiser au moment de la déclaration. Sa valeur peut être affectée ou modifiée en utilisant le constructeur. Donc, cela 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 ex -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Le champ readonly peut alors être initialisé avec des valeurs spécifiques instantanées, comme suit:

A objOne = new A(5);
A objTwo = new A(10);

Ici, l'instance objOne aura la valeur du champ readonly comme 5 et objTwo a 10. Ce qui n'est pas possible en utilisant const.


Ils sont tous deux constants, mais un const est également disponible au moment de la compilation. Cela signifie que l'un des aspects de la différence est que vous pouvez utiliser les variables const comme entrée pour les constructeurs d'attributs, mais pas pour les variables readonly.

Exemple:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

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:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

L'un des membres de l'équipe de notre bureau a fourni les indications suivantes sur l'utilisation de const, static et readonly:

  • Utilisez const lorsque vous avez une variable d'un type que vous pouvez connaître au moment de l'exécution (chaîne littérale, int, double, enums, ...) à laquelle vous voulez que toutes les instances ou consommateurs d'une classe aient accès où la valeur ne devrait pas changer.
  • Utilisez static lorsque vous possédez des données auxquelles vous souhaitez que toutes les instances ou utilisateurs d'une classe aient accès, là où la valeur peut changer.
  • Utilisez static readonly lorsque vous avez une variable d'un type que vous ne pouvez pas savoir au moment de l'exécution (objets) et à laquelle toutes les instances ou les utilisateurs d'une classe doivent avoir accès lorsque la valeur ne doit pas changer.
  • Utilisez readonly lorsque vous avez une variable de niveau d'instance que vous saurez au moment de la création de l'objet qui ne devrait pas changer.

Une dernière remarque: un champ const est statique, mais l'inverse n'est pas vrai.


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é soit à la déclaration, soit dans un constructeur . Par conséquent, les champs en lecture seule peuvent avoir des valeurs différentes selon le constructeur utilisé. De même, alors qu'un champ const est une constante à la compilation , le champ readonly peut être utilisé pour les constantes d' exécution comme dans l'exemple suivant:

public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;

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é soit à la déclaration, soit dans un constructeur. Par conséquent, les champs en lecture seule peuvent avoir des valeurs différentes selon le constructeur utilisé. De même, alors qu'un champ const est une constante à la compilation, le champ readonly peut être utilisé pour les constantes d'exécution comme dans l'exemple suivant:

public static readonly uint l1 = (uint) DateTime.Now.Ticks;

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 de variables const sont remplacées par des valeurs littérales en ligne. Par conséquent, seuls certains types de valeur primitive intégrés peuvent être utilisés de cette manière. Les variables marquées readonly peuvent être définies, dans un constructeur, lors de l'exécution et leur lecture seule est également appliquée pendant l'exécution. Cela implique des coûts de performance minimes, mais cela signifie que vous pouvez utiliser readonly avec n'importe quel type (même les types de référence).

De plus, les variables const sont intrinsèquement statiques, tandis que les variables readonly peuvent être spécifiques à l'instance si vous le souhaitez.


Principalement; Vous pouvez assigner une valeur à un champ statique en lecture seule à une valeur non constante au moment de l'exécution, tandis qu'une valeur constante doit être affectée à const.


Un const doit être codé en dur , où readonly peut être défini dans le constructeur de la classe.


Un autre gotcha .

Puisque const ne fonctionne vraiment qu'avec des types de données basiques, si vous voulez travailler avec une classe, vous pouvez vous sentir "forcé" à utiliser ReadOnly. Cependant, méfiez-vous du piège! ReadOnly signifie que vous ne pouvez pas remplacer l'objet par un autre objet (vous ne pouvez pas le faire se référer à 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!

Donc ne soyez 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 changer ses valeurs internes (pour autant que je sache).


Un const est une constante à la compilation alors que readonly permet de calculer une valeur à l'exécution et de l'initialiser dans le constructeur ou dans le champ. Donc, un 'const' est toujours constant mais 'readonly' est en lecture seule une fois qu'il est assigné.

Eric Lippert de l'équipe C # a plus d'informations sur les différents types d'immutabilité


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 comme un champ, en utilisant le mot-clé const et doivent être initialisées comme elles sont déclarées.

public class MyClass
{
    public const double PI1 = 3.14159;
}

Un membre en readonly est comme une constante en ce sens qu'il représente une valeur immuable. La différence est qu'un membre readonly peut être initialisé au moment de l'exécution, dans un constructeur, tout en pouvant être initialisé à mesure qu'ils sont déclarés.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

const

  • Ils ne peuvent pas être déclarés static (ils sont implicitement statiques)
  • La valeur de constante est évaluée au moment de la compilation
  • les constantes sont initialisées à la déclaration seulement

lecture seulement

  • Ils peuvent être au niveau de l'instance ou statiques
  • La valeur est évaluée au moment de l'exécution
  • readonly peut être initialisé dans la déclaration ou par le code dans le constructeur

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.

Comme exercice, essayez de créer une bibliothèque externe et consommez-la 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 manuellement le fichier EXE, vous devriez trouver que la chaîne constante ne change pas.


Cela l'explique . Résumé: const doit être initialisé au moment de la déclaration, readonly peut être initialisé sur le constructeur (et avoir ainsi une valeur différente selon le constructeur utilisé).

EDIT: Voir Gotcha Gishu ci-dessus pour la différence subtile


const : Impossible de changer n'importe où.

readonly : cette valeur ne peut être modifiée que dans le constructeur. Ne peut pas être changé dans les fonctions normales.


Constant

Nous devons fournir la valeur au champ const quand 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 peut être définie uniquement pour le type primitif comme boolean, char, byte, etc. Les constantes sont toujours considérées comme des membres statiques et non comme des membres d'instance.

Lecture seulement

Les zones en lecture seule ne peuvent être résolues qu'à 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 d'informations sur les deux expliqué ici dans cet article







readonly