为什么DateTime.MinValue不能在C#中用作可选参数

Why DateTime.MinValue can't be used as optional parameter in C#

我正在写一个方法,它将DateTime值作为参数之一。我决定它是可选参数,所以我继续尝试将DateTime.MinValue设为默认值。

1
2
3
private void test(string something, DateTime testVar = DateTime.MinValue) {

}

但是,这会导致以下错误:

Default parameter value for 'testVar' must be a compile-time constant.

使用此代码似乎工作得很好。

1
2
3
private void test(string something, DateTime testVar = new DateTime()) {

}

有人建议我使用datetime.minvalue而不是新的datetime(),因为它是自记录的。既然new DateTime()基本上是同一件事,为什么不能使用DateTime.MinValue呢?如果我把它留给new DateTime(),还会有什么潜在的问题吗?


DateTime.MinValue定义为:

1
public static readonly DateTime MinValue

const不同。由于readonly值不是编译时常量(即编译时不计算该值),因此不能使用。

使用new DateTime()工作的原因是该表达式在编译时已知。这和写default(DateTime)一样。例如,下面表达式中的result == true

1
var result = new DateTime() == default(DateTime);


其他答案涉及了为什么不能使用datetime.minvalue,它不是合法的编译时常量。它是一个static readonly字段,就用法而言,它很可能是常量,但在法律上不是常量,也不适合用作默认参数的规则。关于使用new DateTime()的原因,见C 4.0语言规范第10.6.1节。相关位:

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

这会导致一个初始化为零的实例,基本上是所有零的位模式。(见:第4.1.2节)

但是,在这种情况下,我仍然建议使用DateTime? value = null作为参数和默认参数,特别是当它表示数据库中可以为空的日期时。MinValue不是没有值。null是。


datetime.minvalue是只读的,根据msdn,只读值不是编译时常量:

The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for runtime constants


DateTime.MinValueDateTime.MaxValuepublic static readonly成员,而不是编译时常量。

与其使用DateTime.MinValue作为默认值,不如使用一个可以为空的日期时间(DateTime?)。这使您的意图更加明确,而不是默认为日期时间的尽可能低的值。

像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void test(string something, DateTime? testVar = null )
{
  if ( testVar.HasValue )
  {
     DoSomethingUsefulWithTimestamp( something , testVar.Value ) ;
  }
  else
  {
     DoSomethingElseWithoutTimestamp( something ) ;
  }
  return ;
}

private void DoSomethingUsefulWithTimestamp( string something , DateTime dt )
{
  ... // something useful
}
private void DoSomethingElseWithoutTimestamp( string something )
{
  ... // something useful
}

或者,在方法体中设置默认值:

1
2
3
4
5
6
7
private void test(string something, DateTime? testVar = null )
{
  DateTime dtParameter = testVar ?? DateTime.MinValue ;

  DoSomethingUsefulWithTimestamp( something , dtParameter ) ;

}


另一种选择是有两个方法重载:

  • 接受日期时间参数的
  • 不接受datetime参数的

这样做的好处是,您不必检查参数是否为空,而且您的意图很明显。在内部,方法1可以向数据库添加空值。


基于我所知道的datetime的默认值是datetime.minvalue,所以为什么不使用new datetime()。


使用此语句

1
2
3
4
5
6
7
8
9
10
private void test(string something, DateTime testVar = new DateTime()) {
    if ( testVar != new DateTime() )
    {
        DoSomethingUsefulWithTimestamp( something , testVar.Value ) ;
    }
    else
    {
        DoSomethingElseWithoutTimestamp( something ) ;
    }
}

它应该工作得更好。空值不起作用是一个麻烦,因为它更有意义。