【问题标题】:Why DateTime.MinValue can't be used as optional parameter in C#为什么 DateTime.MinValue 不能用作 C# 中的可选参数
【发布时间】:2012-02-17 23:55:19
【问题描述】:

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

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

}

但是这会产生一个错误:

“testVar”的默认参数值必须是编译时常量。

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

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

}

有人建议我使用 DateTime.MinValue instead of new DateTime(),因为它是自我记录的。既然new DateTime() 基本上是一样的,为什么DateTime.MinValue 不能用?如果我把它留给new DateTime(),也会有任何潜在的问题吗?

【问题讨论】:

  • 替代方法:什么时候将默认值设为 DateTime.MinValue 才有意义?我意识到它是 DateTime 的 default,但它实际上是给定方法的合适值吗?或者,如果没有提供该值,它不应该简单地为空吗?
  • 我一直在使用DateTime.MinValue 从 SQL 获取值为空的值,因为 DateTime 不能为空。 DateTime? 是。
  • 这就是我真正要理解的重点,在这里更适用。如果您要映射到支持可空日期的数据库,则在代码中使用可空日期似乎合适,然后将没有值的日期简单地设为空,就像它们在您的数据库中一样。只是一个想法。
  • 我建议不要使用“DateTime.MinValue”作为可选参数的默认值,而是使用“default(DateTime)”。编译器更喜欢这一点,语义即使不是更清晰也同样清晰。

标签: c# optional-parameters


【解决方案1】:

使用此语句

private void test(string something, DateTime testVar = new DateTime()) {
    if ( testVar != new DateTime() )
    {
        DoSomethingUsefulWithTimestamp( something , testVar.Value ) ;
    }
    else
    {
        DoSomethingElseWithoutTimestamp( something ) ;
    }
}

它应该工作得更好。 null 不起作用真是太可惜了,因为它会更有意义。

【讨论】:

    【解决方案2】:

    其他答案涉及为什么不能使用 DateTime.MinValue,它不是合法的编译时间常数。这是一个static readonly 字段,就用法而言,它很可能是恒定的,但不是合法 恒定的,也不符合可用作默认参数的规则。至于为什么new DateTime()可以可以用,见C# 4.0 Language Specification的10.6.1小节。相关位:

    默认参数中的表达式必须是以下之一:

    · 一个常量表达式

    · new S() 形式的表达式,其中 S 是值类型

    · default(S) 形式的表达式,其中 S 是值类型

    这些导致零初始化实例,基本上是全零的位模式。 (参见:第 4.1.2 节)

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

    【讨论】:

    • 感谢您提供清晰的信息。我希望有一个选项可以接受 2 个答案(一种辅助答案)。
    【解决方案3】:

    DateTime.MinValue 定义为:

    public static readonly DateTime MinValue
    

    这与const 不同。由于 readonly 值不是编译时常量(即该值在编译时评估),因此无法使用。

    使用new DateTime() 起作用的原因是因为该表达式 在编译时是已知的。这与写default(DateTime) 相同。例如,result == true 在以下表达式中:

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

    【讨论】:

      【解决方案4】:

      另一种选择是使用 2 个方法重载:

      • 采用 DateTime 参数的方法
      • 不采用 DateTime 参数的方法

      这样做的好处是您不必检查参数是否为空,并且很清楚您的意图是什么。在内部,方法 1 可以向数据库添加 null。

      【讨论】:

        【解决方案5】:

        DateTime.MinValue(和DateTime.MaxValue)是public static readonly 成员,而不是编译时常量。

        与其使用DateTime.MinValue 作为默认值,不如使用可为空的DateTime (DateTime?)。这使您的意图比默认为可能的最低日期时间值更清楚。

        类似这样的:

        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
        }
        

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

        private void test(string something, DateTime? testVar = null )
        {
          DateTime dtParameter = testVar ?? DateTime.MinValue ;
        
          DoSomethingUsefulWithTimestamp( something , dtParameter ) ;
        
        }
        

        【讨论】:

        • 问题是我在整个代码中都有 DateTime.MinValue 并且我不使用可为空的 DateTime?一点也不。将其修复为跨代码保持一致将是一个杀手。我当然可以为这一次做这件事,但我可能会在某个时候偶然通过 DateTime.MinValue 所以有可能我必须在代码中处理它,因为如果为空,如果 DateTime.MinValue或数数不犯错误:)
        【解决方案6】:

        根据我所知道的 DateTime 的默认值是 DateTime.MinValue 所以为什么不直接使用 new DateTime()

        【讨论】:

        • 那行不通。默认值必须是编译时常量。 new DateTime() 绝对不是编译时常量。
        • @JimMischel 根据我的问题,如果我使用 new DateTime() ,它实际上可以编译得很好。所以我只是想知道/担心它会在某个时候让我反击。
        • 我明白这一点,但根据他所说的,我只是假设他可能会声明一个变量 DateTime someDateTime = new DateTime();这是我对他的问题的理解,我知道这将编译...
        • @JimMischel 根据操作 new DateTime() 工作得很好。
        【解决方案7】:

        DateTime.MinValue 是 readonly,根据 MSDN,只读值不是编译时常量:

        readonly 关键字与 const 关键字不同。 const 字段只能在字段声明时进行初始化。只读字段可以在声明或构造函数中初始化。因此,只读字段可以具有不同的值,具体取决于使用的构造函数。此外,虽然 const 字段是编译时常量,但 readonly 字段可用于运行时常量

        【讨论】:

        • new DateTime 怎么样?为什么它有效?我可以把它留在new DateTime 还是应该使用 null 和可为空的DateTime?
        • 我绝对认为你应该使用 Nullable 的 Datetime
        • @Magnus 我可能会选择 DateTime 的 Nullable,但我想对整个主题进行解释,这样它就不会出现在我的脑海中。每个人似乎都专注于 DateTime.MinValue 这很好,但还有其他问题;)
        猜你喜欢
        • 1970-01-01
        • 2012-08-27
        • 1970-01-01
        • 1970-01-01
        • 2019-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-14
        相关资源
        最近更新 更多