Несоответствие постоянной времени компиляции
Обновление: Это выглядит как красная селедка компилятора, так как на самом деле это действительно так:
const int MyInt = default(int);
Проблема заключается в том, что DateTime
не является допустимым const
, а не использованием default
.
Основной источник путаницы для меня не понимал, что default(DateTime)
обрабатывается специально в необязательных параметрах (и я пришел к ложному выводу о том, что default(DateTime)
рассматривался как константа времени компиляции из-за сообщения об ошибке опуская другие возможные условия). Это ответ Марцин Джурашек в его ответе.
Оригинальный вопрос:
Это бесстыдно разорвано из комментария от Марка Гравелла от этого ответа к другому вопросу.
Почему допустимо следующее:
// No compiler errors, default(DateTime) seems to satisfy the compile-time constant requirement.
public static void DoSomething(DateTime date = default(DateTime))
{
}
Но не следующее:
// Compiler error: "Constant initializer must be compile-time constant.
const DateTime MyDate = default(DateTime);
Как представляется, как бы хотят "константы времени компиляции" (очевидно, если вы попытаетесь предоставить что-то вроде DateTime.MinValue
для необязательного параметра, компилятор жалуется, что он не является константой времени компиляции):
// Compiler error: Default parameter value for 'date' must be a compile-time constant.
public static void DoSomething(DateTime date = DateTime.MinValue) {}
Что происходит за кулисами, из-за чего компилятор обрабатывает их по-другому?
Ответы
Ответ 1
Потому что const
, который может иметь только значение default(TypeOfCost)
, вероятно, будет совершенно бесполезным: -)... И вы не можете его изменить позже: -)
Обратите внимание, что default(TypeOfConst)
есть константное выражение
Из спецификаций С# (5.0): 7.19 Constant expressions
... A constant-expression is an expression that can be fully evaluated at compile-time.
... Only the following constructs are permitted in constant expressions:
... • **Default value expressions**
Ошибка в том, что const DateTime
является незаконным..
10.4 Constants
... The type specified in a constant declaration must be sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum-type, or a reference-type.
Ответ 2
Это описано в спецификации С# (10.6.1):
Фиксированный параметр с аргументом по умолчанию известен как необязательный параметр, тогда как фиксированный параметр без аргумента по умолчанию является требуемый параметр. Необходимый параметр может не отображаться после необязательный параметр в списке формальных параметров.
Параметр A ref
или out
не может иметь аргумент по умолчанию. Выражение в аргументе по умолчанию должен быть одним из следующих:
- константное выражение
- выражение формы
new S()
, где S
- тип значения - выражение формы
default(S)
, где S
- тип значения
Но вы правы, сообщение об ошибке, запрашивающее постоянную времени компиляции, не очень хорошо.
Ответ 3
default()
оценивается во время выполнения. DateTime.MinValue
не объявляется как const.
В объявлениях инициализации и объявления атрибутов могут использоваться только символы, объявленные как const.
Необязательные параметры - это особый случай. Компилятор создает для вас перегрузки. Семантически он хочет const, но технически, по умолчанию это нормально, поскольку компилятор знает, как использовать это в сгенерированной перегрузке.
MSDN заявляет, что необязательные параметры принимают default()
и new()
по дизайну http://msdn.microsoft.com/en-us/library/dd264739.aspx
Что касается определения const,
Постоянное выражение является выражением, которое можно полностью оценить при время компиляции.
Я согласен с тем, что это различие незначительно, и это несколько раз сбивало меня с толку.