Подтвердить что ты не робот

Должен ли я создать объект DateRange?

Несколько моих объектов домена содержат диапазоны дат как пару свойств начала и конца даты:

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.

По моему опыту, глубина иерархии объектов часто усложняет ситуацию. Эти объекты отправляются в отчеты RDLC, отображаемые элементом управления ReportViewer, но это вторичное. Я склоню взгляд к модели, а не наоборот. Однако мы не привязаны к именам свойств и будем соглашаться на компромисс с чем-то вроде:

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 очень и очень грязно.

4b9b3361

Ответ 1

Нет, вы не пропустили класс общего назначения.

У меня есть тип Range в MiscUtil, который может вас заинтересовать, и это, безусловно, упрощает манипуляции DateTime, Ссылаясь на ответ Marc, я не могу вспомнить, является ли это структурой или классом - вы можете, конечно, изменить его.

Это приятно и легко перешагнуть из-за маркеров generics shenanigans (при условии, что вы используете .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
}

(Это также использует кучу методов расширения - более полезно для теста, чем для производства.)

Чтобы ответить на другой вопрос в ответе Марка, Noda Time, безусловно, сможет выразить концепцию даты более подходящей, чем .NET. API, но на данный момент у нас нет ничего похожего на диапазон... Это хорошая идея, хотя - я добавил запрос функции.

Ответ 2

Если вы много работаете с датами, да - диапазон может быть удобным. На самом деле это один из тех редких случаев, когда вы, вероятно, должны писать его как struct (неизменяемый). Обратите внимание, однако, что "Noda Time", вероятно, даст вам все это и многое другое (когда оно будет завершено). Раньше я планировал программное обеспечение; У меня было несколько таких структур (для немного разных заданий).

Обратите внимание: для этого нет удобной конструкции BCL.

Также - подумайте обо всех замечательных методах (и, возможно, операторах), которые вы можете централизовать, когда у вас есть диапазон; "содержит" ( "datetime" другого диапазона, включая/исключая пределы?), "пересекает", смещает (промежуток времени) и т.д. A определенный случай наличия типа для его обработки, Обратите внимание, что на уровне ORM это проще, если ваш ORM поддерживает составные значения - я считаю, что NHibernate делает и, возможно, EF 4.0.

Ответ 3

В .NET 4.0 или более поздней версии был добавлен тип Tuple < > для обработки нескольких значений.

С типом кортежа вы можете определить свою комбинацию значений "на лету". Ваша проблема очень распространена и похожа на то, когда функция хочет вернуть несколько значений. Раньше вам приходилось использовать переменные или создавать новый класс только для ответа функции.

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

Какой бы маршрут вы ни выбрали, я думаю, что вы определенно придерживаетесь правильного подхода. Вы даете реальный смысл тому, что две пары совпадают. Этот самодокументирующий код и, самое главное, прямо в структуре кода.

Ответ 4

Я не знаю какого-либо родного класса .NET типа DateRange. Самая близкая, вероятно, комбинация DateTime + TimeSpan или DateTime/DateTime.

Я думаю, что вы хотите довольно здорово.

Ответ 5

Как уже упоминалось Марк и Джон, я бы создал это как тип значения, который является неизменным. Я бы решил реализовать его как структуру и реализовать интерфейсы IEquatable и IComparable.

При использовании ORM, например NHibernate, вы сможете сохранить тип значения внутри таблицы, которая представляет сущность.