12

Update: This appears to be a compiler red-herring, as the following is actually valid:

const int MyInt = default(int);

The issue lies with DateTime not being a valid const, not the use of default.

The main source of the confusion for me was not realising that default(DateTime) is handled specifically in optional parameters (and I had arrived at a false conclusion that default(DateTime) was being treated as compile-time constant due to the error message omitting the other possible conditions). This is addressed by MarcinJuraszek in his answer.


Original Question:

This is shamelessly ripped from a comment from Marc Gravell from this answer to another question.

Why is the following valid:

// No compiler errors, default(DateTime) seems to satisfy the compile-time constant requirement.
public static void DoSomething(DateTime date = default(DateTime))
{ 
}

But the following not:

// Compiler error: "Constant initializer must be compile-time constant.
const DateTime MyDate = default(DateTime); 

As both appear to want "compile-time constants" (evident if you attempt to provide something like DateTime.MinValue to the optional parameter, the compiler complains that it isn't compile-time constant):

// Compiler error: Default parameter value for 'date' must be a compile-time constant.
public static void DoSomething(DateTime date = DateTime.MinValue) {}

What is going on behind the scenes that causes the compiler to treat these differently?

Community
  • 1
  • 1
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187

3 Answers3

7

That's described in C# specification (10.6.1):

A fixed-parameter with a default-argument is known as an optional parameter, whereas a fixed-parameter without a default-argument is a required parameter. A required parameter may not appear after an optional parameter in a formal-parameter-list.

A ref or outparameter cannot have a default-argument. The expression in a default-argument must be one of the following:

  • a constant-expression
  • an expression of the form new S() where S is a value type
  • an expression of the form default(S) where S is a value type

But you're right, the error message asking for compile-time constant is not good.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • You should also say that default is an operator evaluated at runtime, then this answer is perfect – BlackBear Sep 11 '13 at 12:15
  • @Marcin 7.19 of the C# specifications (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` – xanatos Sep 11 '13 at 12:21
4

default() is evaluated at runtime. DateTime.MinValue is not declared as const.

Only symbols declared as const can be used in member initialisation and attribute declarations.

Optional paramters are a special case. The compiler generates overloads for you. Semantically it wants a const, but technically, default is ok as the compiler knows how to use this in the generated overload.

MSDN states that optional parameters accept default() and new() by design http://msdn.microsoft.com/en-us/library/dd264739.aspx

Concerning the const definition;

A constant expression is an expression that can be fully evaluated at compile time.

I agree that the distinction is slight and it has tripped me up more than once.

Gusdor
  • 14,001
  • 2
  • 52
  • 64
  • 2
    I don't think that covers the question. I know `DateTime.MinValue` is not constant, but in one situation `default(DateTime)` is and in another situation it "isn't". – Adam Houldsworth Sep 11 '13 at 12:08
  • 1
    7.19 of the C# specifications (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` – xanatos Sep 11 '13 at 12:20
4

Because a const that can only have the value default(TypeOfCost) would probably be quite useless :-)... And you can't even change it later :-)

Note that default(TypeOfConst) is a constant-expression

From the C# specifications (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**

The error is that const DateTime is illegal..

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.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Agreed, but the definition of `default(DateTime)` being "compile-time constant" in one situation and not in another is in question, not its use ;-) – Adam Houldsworth Sep 11 '13 at 12:09
  • PI can only have the value 3.14... but I still think it's usefull. – SWeko Sep 11 '13 at 12:11
  • @AdamHouldsworth The error I get is `The type 'System.DateTime' cannot be declared const` – xanatos Sep 11 '13 at 12:12
  • @xanatos Ah, there are two errors there then, build reports both but the IDE only reports one. – Adam Houldsworth Sep 11 '13 at 12:13
  • @AdamHouldsworth A more interesting example that you can add is that you can't use `default(DateTime)` as an attribute parameter :-) – xanatos Sep 11 '13 at 12:13
  • @SWeko PI is one of the 2^64 values of a `double` and it can't be calculated easily. `default(ReferenceType)` == null, `default(ValueType)` == "zeroed ValueType". They are quite simple results. – xanatos Sep 11 '13 at 12:14
  • @xanatos Is that "default value expressions" specifically `default(type)` or literal defaults like `int i = 1;`? – Adam Houldsworth Sep 11 '13 at 12:23
  • @AdamHouldsworth `7.6.13 Default value expressions`... `default-value-expression:`... `default ( type )`. Quite clear, I think – xanatos Sep 11 '13 at 12:24
  • @AdamHouldsworth The limit is in the `const` that can't be used with `DateTime`. I've found the piece of specifications that tells it. Probably they thought that `default(ValueType)` was quite useless (and as a singleton constant value calculable at compile time) and so they limited the `const`. – xanatos Sep 11 '13 at 12:26
  • @xanatos Yes, the same issue occurs with attribute parameters re your comment above, `default(int)` is valid in an attribute parameter. It appears that this compiler error message trumps the one about attempting to use `DateTime` in the first place. – Adam Houldsworth Sep 11 '13 at 12:28