const
et readonly
sont similaires, mais ils ne sont pas exactement les mêmes.
Un const
champ est une constante au moment de la compilation, ce qui signifie que cette valeur peut être calculée au moment de la compilation. Un readonly
champ permet des scénarios supplémentaires dans lesquels du code doit être exécuté lors de la construction du type. Après la construction, unreadonly
champ ne peut pas être modifié.
Par exemple, les const
membres 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 au moment de la 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:
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 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 readonly
mot - clé dans les déclarations, nous préservons l'initialisation flexible tout en empêchant le code client de contourner.
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, 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:
public class A
{
public static const C = 0;
}
et un développeur différent a écrit du 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 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.
static readonly
: essayez d'utiliser un const à l'intérieur d'unIEnumerator
qui déclencherait une irrécupérableyield
et vous obtiendrez une "erreur de compilation interne" redoutée . Je n'ai pas testé le code en dehors d'Unity3D, mais j'espère qu'il s'agit d'un bug mono ou .NET . C'est néanmoins un problème c # .