【问题标题】:Constant DateTime in C#C# 中的常量日期时间
【发布时间】:2011-10-15 03:27:56
【问题描述】:

我想在属性参数中放置一个恒定的日期时间,我如何制作一个恒定的日期时间?它与 EntLib 验证应用程序块的 ValidationAttribute 相关,但也适用于其他属性。

当我这样做时:

private DateTime _lowerbound = new DateTime(2011, 1, 1);
[DateTimeRangeValidator(_lowerbound)]

我会得到:

An object reference is required for the non-static field, method, or property _lowerbound

通过这样做

private const DateTime _lowerbound = new DateTime(2011, 1, 1);
[DateTimeRangeValidator(_lowerbound)]

我会得到:

类型“System.DateTime”不能声明为 const

有什么想法吗?走这条路并不可取:

[DateTimeRangeValidator("01-01-2011")]

【问题讨论】:

    标签: c# datetime attributes constants


    【解决方案1】:

    正如一些较早的回复所指出的,const DateTime 在 C# 中不受本机支持,并且不能用作属性参数。不过,readonly DateTime(在 Effective C#,第 2 版 [Item 2] 中推荐使用 const)是其他情况的简单解决方法,如下所示:

    public class MyClass
    {
        public static readonly DateTime DefaultDate = new DateTime(1900,1,1);
    }
    

    【讨论】:

    • 虽然这个静态只读成员仍然不能在属性参数中使用
    【解决方案2】:

    我一直读到的解决方案是使用字符串的路径,或者将日/月/年作为三个单独的参数传递,因为 C# 目前不支持 DateTime 文字值。

    下面是一个简单的示例,它可以让您将int 类型的三个参数或string 类型的参数传递给属性:

    public class SomeDateTimeAttribute : Attribute
    {
        private DateTime _date;
    
        public SomeDateTimeAttribute(int year, int month, int day)
        {
            _date = new DateTime(year, month, day);
        }
    
        public SomeDateTimeAttribute(string date)
        {
            _date = DateTime.Parse(date);
        }
    
        public DateTime Date
        {
            get { return _date; }
        }
    
        public bool IsAfterToday()
        {
            return this.Date > DateTime.Today;
        }
    }
    

    【讨论】:

    • 这是构造函数吗?我还不明白。能否提供更多代码?
    • 是的,抱歉,我已经更新了一个示例,希望能澄清一下。
    • 请注意,第二个重载有一个缺陷,因为DateTime 是一个结构,不能为空。这意味着如果TryParse 失败,不会抛出错误,DateTime 属性将返回DateTime 结构的默认值,即0001-01-01 00:00:00。这可能会导致无法正确执行验证。
    • 行得通!一旦使用该属性的类被实例化(据我所知),至少现在会抛出一个错误。
    【解决方案3】:

    DateTimeRangeValidator 可以将字符串表示(ISO8601 格式)作为参数

    例如

                                LowerBound              UpperBound
    [DateTimeRangeValidator("2010-01-01T00:00:00",  "2010-01-20T00:00:00")]
    

    单个参数将被解释为 UpperBound,因此如果要输入 LowerBound,则需要 2。检查文档以查看 UpperBound 是否有特殊的 “不关心” 值,或者您是否需要将其设置为非常遥远的未来日期。

    哎呀,刚刚重新阅读并注意到了

    '不走这条路'

    [DateTimeRangeValidator("01-01-2011")]
    

    为什么不呢?

    private const string LowerBound = "2010-01-01T00:00:00";
    private const string UpperBound = "2010-01-20T00:00:00";
    
    [DateTimeRangeValidator(LowerBound, UpperBound)]
    

    比(VB 日期文字格式)更差/不同

    private const DateTime LowerBound = #01/01/2000 00:00 AM#;
    private const DateTime UpperBound = #20/01/2000 11:59 PM#;
    
    [DateTimeRangeValidator(LowerBound, UpperBound)]
    

    hth,
    艾伦

    【讨论】:

    • 我知道我可以走这条路,但如前所述,这并不可取......我想知道我是否可以让它更稳固一点。
    • VB 日期文字相对于使用字符串文字来表示日期的优势在于,带有 VB 日期文字的问题将导致编译时错误,而带有字符串的问题文字将导致运行时错误。这样,它也避免了拆箱操作。
    • 就编译时间与运行时间达成一致。
    • “避免拆箱”是什么意思?该属性有多个 ctors,一些取日期,另一些是字符串。如果使用该字符串,则解析会影响性能,我可以看到这一点,但我没有看到拆箱问题。这是一个诚实的问题,我不反对你,只是不完全理解评论。
    • #20/01/2000 11:59 PM# 是无效的日期文字。该订单是我们来自美国的月/日/年错误订单,而不是从最小到最大的日/月/年订单。幸运的是,C# 也没有搞砸这一点。但是 C# 确实需要 ISO 日期文字。 #2014-06-13# 将是一个很好的解决方案。我不太喜欢他们选择哪种语法,只要他们不使用我们在美国流行使用的愚蠢的月/日/年顺序。
    【解决方案4】:

    老问题,但这是另一个解决方案:

     public DateTime SOME_DATE
     {
          get
          {
               return new Date(2020, 04, 03);
          }
          set
          {
               throw new ReadOnlyException();
          }
     }
    

    此解决方案的主要优点是它允许您将日期存储在 DateTime 中,而不必使用字符串。如果你愿意,你也可以不抛出任何异常,在片场什么也不做。

    【讨论】:

    • 虽然这可能满足问题的部分标题,但它仍然不允许您将 DateTime 值指定为属性的参数。
    • 另外,不要在set 子句中抛出异常,只需将其省略即可。它将属性更改为只读属性,并将在编译时强制执行,这比在运行时抛出异常要好得多。
    猜你喜欢
    • 2017-01-28
    • 2012-01-20
    • 1970-01-01
    • 2017-09-22
    • 2019-09-06
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多