Должен ли я создать объект DateRange?
-
12-09-2019 - |
Вопрос
Некоторые из моих объектов домена содержат диапазоны дат в виде пары свойств даты начала и окончания:
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, вы сможете хранить тип значения внутри таблицы, которая представляет сущность.