Const и readonly похожи, но они не совсем одинаковы. Константное поле - это константа времени компиляции, что означает, что это значение может быть вычислено во время компиляции. Поле «только для чтения» включает дополнительные сценарии, в которых некоторый код должен выполняться во время конструирования типа. После создания поле только для чтения не может быть изменено.
Например, константные члены могут использоваться для определения таких членов, как:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
, поскольку такие значения, как 3.14 и 0, являются константами времени компиляции. Тем не менее, рассмотрим случай, когда вы определяете тип и хотите предоставить некоторые заранее созданные экземпляры этого типа. Например, вы можете определить класс Color и предоставить «константы» для общих цветов, таких как черный, белый и т. Д. Это невозможно сделать с помощью константных членов, поскольку правые части не являются константами времени компиляции. Это можно сделать с помощью обычных статических элементов:
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;
}
}
но тогда ничто не может помешать клиенту Color с ним взломать, возможно, путем обмена значениями Black и White. Излишне говорить, что это вызвало бы смятение у других клиентов класса Color. Функция «только для чтения» предназначена для этого сценария. Просто вводя ключевое слово readonly в объявлениях, мы сохраняем гибкую инициализацию, предотвращая приглушение кода клиента.
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;
}
}
Интересно отметить, что константные члены всегда являются статическими, тогда как член только для чтения может быть статическим или нет, как обычное поле.
Возможно использовать одно ключевое слово для этих двух целей, но это приводит либо к проблемам с версиями, либо к проблемам с производительностью. Предположим на минуту, что мы использовали одно ключевое слово для этого (const), и разработчик написал:
public class A
{
public static const C = 0;
}
и другой разработчик написал код, основанный на A:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
Теперь, может ли генерируемый код основываться на том факте, что A.C является константой времени компиляции? Т.е. можно ли просто использовать A.C значением 0? Если вы скажете «да» на это, то это означает, что разработчик A не может изменить способ инициализации A.C - это связывает руки разработчика A без разрешения. Если вы ответите «нет» на этот вопрос, то пропустите важную оптимизацию. Возможно, автор A уверен, что A.C всегда будет нулевым. Использование как const, так и readonly позволяет разработчику A указать намерение. Это улучшает поведение при управлении версиями и повышает производительность.