Подтвердить что ты не робот

Почему константы могут быть неявно преобразованы, а статические поля readonly не могут?

Учитывая приведенный ниже код, мне интересно, почему referenceValue = ConstantInt; действителен, а referenceValue = StaticInt; не удается скомпилировать.

namespace Demo
{
    public class Class1
    {
        private const int ConstantInt = 42;
        private static readonly int StaticInt = 42;

        public void DemoMethod(ref uint referenceValue)
        {
            referenceValue = ConstantInt; // This compiles
            referenceValue = StaticInt; // This claims that the source type 'int' cannot be converted to 'unit' implicitly. 
        }
    }
}
4b9b3361

Ответ 1

Константы заменяются во время компиляции с их соответствующим значением. Поэтому с точки зрения компилятора это referenceValue = ConstantInt; совпадает с этим referenceValue = 42.

В то время как поля readonly похожи, они не являются. Их ценность не известна во время компиляции. Они поддерживаются статическим полем класса. Их значение может быть вычислено, даже модифицировано из статического конструктора, поэтому компилятор не может проверить, что значение находится в диапазоне uint во время компиляции.

Например:

public class Class1
{
    private const int ConstantInt = 42;
    private static readonly int StaticInt = 42;

    static Class1()
    {
        StaticInt = -20;
    }

    public void DemoMethod(ref uint referenceValue)
    {
        referenceValue = StaticInt; // it -20
    }
}

Edit

Как отмечалось в комментариях, не все задания от констант к переменным работают, переменная long constant to int не работает без явного приведения. Это поведение одинаково основано на типе константы, независимо от того, является ли она именованной константой или встроенной константой:

private const long ConstantInt = 42;
// Both of these will cause an error:
referenceValue = ConstantInt; // can't be converted implicitly
referenceValue = 42L; // but neither can an inline long constant (the L makes it long)

Ответ 2

Поскольку постоянные поля оцениваются во время компиляции, а поля readonly оцениваются во время выполнения. Интерпретатор в компиляторе рассматривает ваши целые числа иначе, чем выполняется во время выполнения.

Компилятор распознает значение и его тип, и он может сделать базовое преобразование, основанное на этом, как и в этом случае. Попробуйте посмотреть, что произойдет, если вы установите ConstantInt на отрицательное число. Компилятор отключится. То же самое верно при изменении типа на long или float: нет правила преобразования компилятора, поэтому он также ошибочно.

Ответ 3

из doc

Ключевое слово readonly отличается от ключевого слова const. Поле const может быть инициализировано только при объявлении поля. Поле readonly может быть инициализировано либо в объявлении, либо в конструкторе. Поэтому поля readonly могут иметь разные значения в зависимости от используемого конструктора. Кроме того, хотя константное поле является константой времени компиляции, поле readonly может использоваться для констант времени выполнения

как в этой строке: public static readonly uint l1 = (uint) DateTime.Now.Ticks;