Ce sont des types de valeurs immuables sur la pile. Qu'est-ce qui m'empêche d'avoir un const?
Références:
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.)
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.
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.
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.