const
и readonly
похожи, но они не совсем одинаковы.
const
Поле является константой времени компиляции, а это означает , что это значение может быть вычислено во время компиляции. readonly
Поле позволяет устанавливать дополнительные сценарии , в которых какой - то код должен быть запущен во время строительства этого типа. После строительства readonly
поле не может быть изменено.
Например, const
члены могут использоваться для определения таких членов, как:
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, green, blue) = (r, g, 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, green, blue) = (r, g, b);
}
Интересно отметить, что члены-константы всегда являются статическими, тогда как член только для чтения может быть статическим или нет, как обычное поле.
Для этих двух целей можно использовать одно ключевое слово, но это приводит либо к проблемам с версиями, либо к проблемам с производительностью. Предположим на минуту, что мы использовали одно ключевое слово для этого (const), и разработчик написал:
public class A
{
public static const C = 0;
}
и другой разработчик написал код, который опирался на A:
public class B
{
static void Main() => Console.WriteLine(A.C);
}
Теперь, может ли генерируемый код опираться на тот факт, что AC является константой времени компиляции? Т.е. можно ли просто заменить использование AC значением 0? Если вы скажете «да» на это, то это означает, что разработчик A не может изменить способ инициализации AC - это связывает руки разработчика A без разрешения.
Если вы ответите «нет» на этот вопрос, то пропустите важную оптимизацию. Возможно, автор A уверен, что AC всегда будет нулевым. Использование const и readonly позволяет разработчику A указать намерение. Это улучшает поведение при управлении версиями, а также повышает производительность.
static readonly
: попробуйте использовать const внутри,IEnumerator
который вызовет необратимое,yield
и вы получите страшную «Внутреннюю ошибку компилятора» . Я не тестировал код вне Unity3D, но я уверен, что это ошибка в моно или .NET . Это C # вопрос , тем не менее.