web-dev-qa-db-fra.com

Pourquoi les structures ne peuvent-elles pas être déclarées const?

38
Lazlo

Parce que le constructeur du type valeur peut faire n'importe quoi - par exemple, changer de logique en fonction de l'heure de la journée. Les types à valeur constante ont un sens intellectuellement, mais cela ne peut tout simplement pas fonctionner sur les types de valeur personnalisés en raison de la flexibilité des constructeurs pour faire ce qu'ils veulent. (N'oubliez pas que les constantes sont évaluées à au moment de la compilation ce qui signifie que votre constructeur devrait être exécuté au moment de la compilation.)

44
cdhowie

Const en C # signifie qu'il peut être déterminé au moment de la compilation, c'est pourquoi seuls les types très primitifs tels que int et string peuvent être const.

Si vous venez d'un arrière-plan C, le mot clé readonly pourrait mieux vous convenir.

22
vcsjones

Pour que le compilateur C # produise une valeur const d'un type de structure, il doit savoir quelles valeurs doivent aller dans tous ses champs. Le compilateur C # sait intrinsèquement comment initialiser les champs de certains types comme Decimal, mais pour la plupart des types de valeur, il n'a pas de telles connaissances.

Il serait possible pour un compilateur de fournir un moyen de déclarer des valeurs constantes d'un type de structure dans des contextes où tous les champs struct étaient exposés. Si les champs d'une structure étaient private, les constantes de ce type ne pourraient alors être déclarées que dans la structure; si les champs étaient internal, les constantes pourraient être déclarées n'importe où dans l'assembly; si public, ils pourraient être déclarés n'importe où.

Bien que j'aimerais voir une telle fonctionnalité, je ne m'attends pas à ce que des langages .net traditionnels la mettent en œuvre. Les constantes nommées de types connus du compilateur peuvent participer à d'autres expressions constantes, tandis que static readonly les variables ne le peuvent pas. Si NumRows est une constante égale à 4, une expression comme Arr[3*NumRows+7] peut être remplacé par Arr[19] même si NumRows est défini dans un assembly extérieur. Cela donne à ces constantes un avantage substantiel sur static readonly variables. Si, cependant, une constante est d'un type qu'un compilateur ne reconnaît pas intrinsèquement, elle aurait une capacité très limitée de participer à toutes les expressions constantes, annulant efficacement l'avantage d'être une constante en premier lieu. Si une constante de type valeur avait un champ exposé, il serait possible pour un compilateur d'utiliser la valeur de ce champ comme constante, mais comme les créateurs des langages .net sont philosophiquement opposés aux structures avec des champs exposés, je ne m'attendrais pas à leur permettre une telle utilisation même s'ils le pouvaient.

Il y aurait des cas d'utilisation potentiels pour favoriser les constantes sur static readonly variables, mais de nombreux cas de ce type peuvent être traités de manière acceptable à l'aide des types existants. Par exemple, une bibliothèque peut exposer un const Int64 pour coder les informations sur sa version et utiliser cette valeur comme valeur de paramètre par défaut pour une méthode GetLinkedVersionInfo. La valeur en question serait "intégrée" dans le code appelant lors de sa compilation, permettant ainsi à la méthode de signaler la version de la bibliothèque à laquelle l'appelant était lié, et éventuellement d'identifier s'il y a des problèmes de compatibilité avec la version qu'il exécute.

4
supercat

Je viens de tester le mot clé readonly avec une simple structure mutable:

struct Test
{
   public int value;

   public void setInt(int val)
   {
      value = val;
   }
}

static class Program
{
   public static readonly Test t = new Test();

   static void Main()
   {
      Console.WriteLine(t.value); // Outputs "0"
      t.setInt(10);
      //t.value = 10;  //Illegal, will not let you assign field of a static struct
      Console.WriteLine(t.value); // Still outputs "0"
   }
}

Même si une structure readonly n'est pas techniquement une constante de temps de compilation, le runtime ne la laissera pas changer. Même en accélérant, la méthode setInt() ressemble à des changements de valeur, mais ne montre pas le changement dans Main.

Je suppose que la structure elle-même est placée dans la mémoire "en lecture seule", les empêchant de changer. Contrairement à une classe, qui maintient simplement le pointeur constant, permettant aux champs de classe eux-mêmes de changer comme ils le souhaitent.

Il semble donc que static readonly Soit effectivement un const, même pour les structures mutables.

3
Cemafor