我应该创建一个 DateRange 对象吗?

发布于 2024-08-13 15:35:17 字数 1353 浏览 5 评论 0原文

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

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 类型污染我的公共域方法签名感觉非常非常肮脏。

A few of my domain objects contain date ranges as a pair of start and end date properties:

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; }
}

And I find myself with a lot of this:

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);

The last one made me wonder ... Should I implement a DateRange class? I'm not aware of one in the BCL.

In my experience, making the object hierarchy deeper often complicates things. These objects do get sent to RDLC reports displayed by the ReportViewer control, but that's secondary. I'll bend the view to the model rather than vice versa. We aren't tied to the property names, though, and would be willing to compromise with something like:

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

Period p = new Period();
DateTime t = p.EffectiveDateRange.StartDate;

A benefit of a DateRange class would be centralized validation of the end date coming after the start date, and it will simplify my method signatures:

abstract public int Foo(DateRange dateRange);
abstract public decimal Bar(DateRange dateRange);
abstract public ICollection<DateRange> FooBar(DateRange dateRange);

I'm just not sure that a DateRange class won't get me into more trouble than its worth. Opinions?

Side question: Did I miss a generic general-purpose tuple class in the BCL somewhere? I know there's some very specific ones floating around in various namespaces. Polluting my public domain method signatures with C5 types feels very, very dirty.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

琉璃梦幻 2024-08-20 15:35:17

不,您没有错过通用课程。

我在 MiscUtil 中有一个 Range 类型,您可能对此感兴趣- 它确实可以进行简单的 DateTime 操作。参考马克的回答,我不记得这是一个结构还是一个类 - 当然欢迎您更改它。

由于 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 更恰当地表达日期的概念,但我们目前没有类似范围之类的东西......不过这是一个好主意- 我添加了功能请求

No, you didn't miss a general purpose class.

I have a Range type in MiscUtil which you may be interested in - and it certainly makes for simple DateTime manipulation. Referring to Marc's answer, I can't remember whether this is a struct or a class - you'd be welcome to change it of course.

It's nice and easy to step through, due to Marc's generics shenanigans (assuming you're using .NET 3.5, at least - it's feasible with 2.0 but not supported at the moment);

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

foreach (DateTime date in range.Step(1.Days())
{
    // I was alive in this day
}

(That's also using a bunch of extension methods - more useful for test than production.)

To address the other point in Marc's answer, Noda Time will certainly be able to express the concept of a date more appropriately than the .NET API, but we don't have anything like a range at the moment... It's a nice idea though - I've added a feature request.

你在我安 2024-08-20 15:35:17

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

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

Tuple<DateTime, DateTime> dateRange =
    new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now);

无论你走哪条路,我想你都绝对是走对了路。您对配对的两个日期赋予了真正的意义。这是自我记录的代码,并且以最好的方式,就在代码的结构中。

In .NET 4.0 or higher the Tuple<> type was added to handle multiple values.

With the tuple type you can define your own combination of values on the fly. Your problem is very common and is similar to when a function wants to return multiple values. Previously you had to use out variables or create a new class just for the function's response.

Tuple<DateTime, DateTime> dateRange =
    new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now);

Whichever route you take, I think you are definitely taking the correct approach. You are giving real meaning to what two dates paired together are. That's self-documenting code and in the greatest way, right in the structure of the code.

叶落知秋 2024-08-20 15:35:17

如果您对日期做了很多工作,是的 - 范围可以很方便。这实际上是一种非常罕见的情况,您应该可能将其编写为struct(不可变)。但请注意,“野田时间”可能会为您提供所有这些以及更多内容(当它完成时)。我以前做过调度软件;我有几个这样的结构(用于稍微不同的工作)。

请注意,没有一个方便的 BCL 构造可以实现此目的。

另外 - 想想当你有一个范围时你可以集中所有精彩的方法(可能还有运算符); “包含”(日期时间?另一个范围?包括/排除限制?),“相交”,偏移量(时间跨度)等。有一个类型来处理它的明确情况。请注意,在 ORM 级别,如果您的 ORM 支持复合值,这会更容易 - 我相信 NHibernate 可以,也可能是 EF 4.0。

If you do a lot of work with dates, yes - a range can be handy. This is actually one of those oh-so-rare cases where you should probably write it as a struct (immutable). Note, however, that "Noda Time" will probably give you all of this and more (when it is complete). I've done scheduling software before; I had a couple of such structs (for slightly different jobs).

Note, there isn't a handy BCL construct for this.

Also - think of all the wonderful methods (and possibly operators) that you can centralise when you have a range; "contains" (of a datetime? of another range? including/excluding limits?), "intersects", offset-by (a timespan), etc. A definite case for having a type to handle it. Note that at the ORM level, this is easier if your ORM supports composite values - I believe NHibernate does, and possibly EF 4.0.

维持三分热 2024-08-20 15:35:17

我不知道任何具有 DateRange 性质的本机 .NET 类。最接近的可能是 DateTime+TimeSpan 或 DateTime/DateTime 组合。

我认为你想要的是相当合理的。

I do not know of any native .NET class of the DateRange nature. The closest is probably DateTime+TimeSpan or DateTime/DateTime combination.

I think what you want is fairly sound.

古镇旧梦 2024-08-20 15:35:17

正如马克和乔恩已经提到的,我会将其创建为值类型,它是不可变的。我会选择将其实现为结构体,并实现 IEquatable 和 IComparable 接口。

当使用像 NHibernate 这样的 ORM 时,您将能够将值类型存储在代表实体的表中。

As Mark and Jon already mentioned, I would create this as a value-type, which is immutable. I would opt to implement it as a struct, and implement the IEquatable and IComparable interfaces.

When using an ORM like NHibernate, you will be able to store the value type inside a table which represents an entity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文