我的一些域对象将日期范围包含为一对开始日期和结束日期属性:
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; }
}
我发现自己有很多这样的事情:
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);
最后一个让我想知道......我应该实现一个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;
DateRange类的好处是集中验证开始日期之后的结束日期,它将简化我的方法签名:
abstract public int Foo(DateRange dateRange);
abstract public decimal Bar(DateRange dateRange);
abstract public ICollection<DateRange> FooBar(DateRange dateRange);
我只是不确定DateRange类不会让我遇到麻烦而不是它的价值。意见?
附带问题:我是否错过了某个BCL中的通用通用元组类?我知道在各种命名空间中有一些非常具体的东西。用C5类型污染我的公共领域方法签名感觉非常非常脏。
答案 0 :(得分:38)
不,你没有错过通用课程。
我在MiscUtil中有Range
类型您可能感兴趣 - 这肯定会导致简单的DateTime
操作。谈到Marc的回答,我不记得这是一个结构还是一个类 - 当然欢迎你改变它。
由于Marc的泛型恶作剧(假设您使用的是.NET 3.5,至少 - 它在2.0时可行,但目前不支持),这很容易让步:
Range<DateTime> range = 19.June(1976).To(DateTime.Today);
foreach (DateTime date in range.Step(1.Days())
{
// I was alive in this day
}
(这也是使用一堆扩展方法 - 对于测试比生产更有用。)
为了解决Marc的答案中的另一点,Noda Time肯定能够比.NET API更恰当地表达日期的概念,但我们目前没有像范围那样的东西。 ..虽然这是个好主意 - 我添加了feature request。
答案 1 :(得分:9)
在.NET 4.0或更高版本中,元组&lt;&gt;添加了类型以处理多个值。
使用元组类型,您可以动态定义自己的值组合。您的问题很常见,类似于函数想要返回多个值时。以前,您必须使用变量或仅为函数的响应创建一个新类。
Tuple<DateTime, DateTime> dateRange =
new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now);
无论你采取哪种方式,我认为你肯定采取了正确的方法。你正在给两个日期配对的真正含义。这是自我记录的代码,最好的方式是代码结构。
答案 2 :(得分:5)
如果您使用日期做了很多工作,是的 - 范围可以很方便。这实际上是其中一个非常罕见的情况,其中应该可能将其写为struct
(不可变)。但请注意,“Noda Time”可能会为您提供所有这些以及更多(当它完成时)。我以前做过调度软件;我有几个这样的结构(略有不同的工作)。
注意,没有方便的BCL结构。
另外 - 想想你拥有一个范围时可以集中的所有精彩方法(以及可能的操作符); “包含”(另一个范围的日期时间?包括/排除限制?),“相交”,偏移(一个时间跨度)等。明确情况下有一个类型来处理它。请注意,在ORM级别,如果您的ORM支持复合值,这会更容易 - 我相信NHibernate会这样做,而且可能是EF 4.0。
答案 3 :(得分:0)
我不知道DateRange性质的任何本机.NET类。最接近的可能是DateTime + TimeSpan或DateTime / DateTime组合。
我认为你想要的是相当合理的。
答案 4 :(得分:0)
正如Mark和Jon已经提到的那样,我会将其创建为值类型,这是不可变的。我会选择将它作为结构实现,并实现IEquatable和IComparable接口。
当使用像NHibernate这样的ORM时,您将能够将值类型存储在表示实体的表中。