Вопрос

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

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 кажется очень, очень грязным.

Это было полезно?

Решение

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

у меня есть Range введите РазноеUtil которые могут вас заинтересовать – и это, безусловно, упрощает DateTime манипуляция.Что касается ответа Марка, я не могу вспомнить, является ли это структурой или классом - вы, конечно, можете изменить ее.

Это приятно и легко пройти благодаря махинациям Марка с дженериками (при условии, что вы используете, по крайней мере, .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
}

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top