我应该制作一个DateRange对象吗?

que*_*rin 61 .net tuples model date-range

我的一些域对象包含日期范围作为一对开始和结束日期属性:

public class Period {
  public DateTime EffectiveDate { get; set; }
  public DateTime ThroughDate { get; set; }
}

public class Timeline {
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我发现自己有很多这样的事情:

abstract public int Foo(DateTime startDate, DateTime endDate);
abstract public decimal Bar(DateTime startDate, DateTime endDate);
abstract public ICollection<C5.Rec<DateTime, DateTime>> FooBar(DateTime startDate, DateTime endDate);
Run Code Online (Sandbox Code Playgroud)

最后一个让我想知道......我应该实现一个DateRange类吗?我不知道BCL中有一个.

根据我的经验,使对象层次结构更深入往往使事情复杂化.这些对象确实被发送到ReportViewer控件显示的RDLC报告,但这是次要的.我会将视图弯曲到模型而不是相反.但是,我们并不依赖于属性名称,并愿意与以下内容妥协:

public class DateRange {
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

Period p = new Period();
DateTime t = p.EffectiveDateRange.StartDate;
Run Code Online (Sandbox Code Playgroud)

DateRange类的一个好处是集中验证开始日期之后的结束日期,它将简化我的方法签名:

abstract public int Foo(DateRange dateRange);
abstract public decimal Bar(DateRange dateRange);
abstract public ICollection<DateRange> FooBar(DateRange dateRange);
Run Code Online (Sandbox Code Playgroud)

我只是不确定DateRange类不会让我比它的价值更麻烦.意见?

附带问题:我是否错过了BCL中某个通用的通用元组类?我知道在各种命名空间中有一些非常具体的东西.用C5类型污染我的公共领域方法签名感觉非常非常脏.

Jon*_*eet 40

不,你没有错过一个通用课程.

我有一个你可能感兴趣的MiscUtilRange类型- 它肯定会让简单的操作.谈到Marc的回答,我不记得这是一个结构还是一个类 - 当然欢迎你改变它.DateTime

由于Marc的泛型恶作剧(假设你使用的是.NET 3.5,至少它是可行的,但目前不支持),这很容易让步.

Range<DateTime> range = 19.June(1976).To(DateTime.Today);

foreach (DateTime date in range.Step(1.Days())
{
    // I was alive in this day
}
Run Code Online (Sandbox Code Playgroud)

(这也使用了一堆扩展方法 - 对于测试比生产更有用.)

为了解决Marc的答案中的另一点,Noda Time肯定能够比.NET API更恰当地表达日期的概念,但是我们目前没有像范围那样的东西......这是一个好主意虽然 - 我添加了一个功能请求.


Tim*_*lez 12

在.NET 4.0或更高版本中,添加了Tuple <>类型以处理多个值.

使用元组类型,您可以动态定义自己的值组合.您的问题很常见,类似于函数想要返回多个值时.以前,您必须使用变量或仅为函数的响应创建一个新类.

Tuple<DateTime, DateTime> dateRange =
    new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now);
Run Code Online (Sandbox Code Playgroud)

无论你采取哪种方式,我认为你肯定采取了正确的方法.你正在给两个日期配对的真正含义.这是自我记录的代码,并且以最好的方式,正好在代码的结构中.


Mar*_*ell 5

如果你做了很多关于日期的工作,是的 - 范围可以很方便.这实际上是那些非常罕见的情况之一,你应该把它写成struct(不可变的).但请注意,"Noda Time"可能会为您提供所有这些以及更多(当它完成时).我以前做过调度软件; 我有几个这样的结构(略有不同的工作).

注意,没有方便的BCL结构.

此外 - 想想你拥有一个范围时可以集中的所有精彩方法(以及可能的操作员); "包含"(另一个范围的日期时间?包括/排除限制?),"相交",偏移(一个时间跨度)等.具有处理它的类型的明确情况.请注意,在ORM级别,如果您的ORM支持复合值,这会更容易 - 我相信NHibernate,以及可能的EF 4.0.