Несоответствие постоянной времени компиляции

Обновление: Это выглядит как красная селедка компилятора, так как на самом деле это действительно так:

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,

Постоянное выражение является выражением, которое можно полностью оценить при время компиляции.

Я согласен с тем, что это различие незначительно, и это несколько раз сбивало меня с толку.