Вопрос

Класс TimeSheetActivity имеет коллекцию распределений.Распределение - это объект значения, который также используется другими объектами в домене и выглядит примерно так:

public class Allocation : ValueObject
{
    public virtual StaffMember StaffMember { get; private set; }
    public virtual TimeSheetActivity Activity { get; private set; }
    public virtual DateTime EventDate { get ... }
    public virtual TimeQuantity TimeSpent { get ... }
}

Повторяющиеся выделения для одного и того же выделения.Дата события не допускается.Таким образом, когда клиент пытается выполнить выделение для действия, выполняется проверка, чтобы увидеть, есть ли уже выделение в коллекции для такого же выделения.EventDate.Если нет, то новое распределение добавляется в коллекцию, но если это так, существующее распределение заменяется новым.

В настоящее время я использую словарь для поддержания коллекции с выделением.EventDate в качестве ключа.Это отлично работает для домена, но мне интересно, не является ли тот факт, что ключ уже является частью значения, сам по себе "плохим запахом".

У меня также нет причин сохранять что-либо, кроме значений словаря.Поскольку я использую NHibernate, мне может понадобиться написать какой-нибудь пользовательский тип для этого, и мне интересно, не является ли это также признаком того, что мне следует использовать другой тип коллекции.(Это также является причиной виртуальных свойств в классе распределения).

Основной альтернативой, о которой я думаю, был бы HashSet с выделенным EqualityComparer .

А ты как думаешь?

Приветствую, Беррил

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

Решение

Если вы используете внешний компаратор для выполнения HashSet<Allocation>, вам нужно было бы быть очень осторожным, чтобы не изменять дату без повторного ввода значения в словаре.У вас есть эта проблема в любом случае, но она усугубляется изменчивостью (по крайней мере, с Dictionary<,> он по-прежнему сможет отслеживать свои собственные ключи и значения).Используя изменяемое значение как часть ключа, вы рискуете никогда больше не увидеть это значение...

Когда я работал над системами расписания в прошлом, я действительно использовал SortedList<,> для этого - аналогично, но полезно, если вам обычно нужны данные в последовательности, и позволяет выполнять двоичный поиск, если данные достаточно однородны.

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

Я не думаю, что тот факт, что ключ является частью значения, обязательно является проблемой.По моему опыту, это довольно часто случается со словарями.A HashSet с соответствующим средством сравнения равенства, безусловно, сработало бы, при условии, что вам никогда не нужно было обращаться к текущему объекту с определенным EventDate.Потенциально это кажется полезной вещью, которую нужно уметь делать...

Вы в настоящее время просто обеспокоены несколько смутно, или у вас есть конкретные подозрения относительно того, как это может вас задеть?

Используя стандартные библиотеки, я не знаю лучшего решения, чем это.Тем не менее, я также почувствовал, что от такого кода "дурно пахнет", но это из-за классов коллекции в BCL, а не вашего кода.

Я не знаю, почему MS не создала универсальные наборы<TKey, TData> where TData: IKeyed<TKey> или так вместо Словарей, потому что это позволило бы реализовать такие структуры данных, где ключ является частью данных.В KeyValuePair<TKey, TValue>: IKeyed<TKey> это была бы просто вспомогательная структура, реализующая этот интерфейс и, таким образом, позволяющая создавать идентичные функциональные возможности словаря в том виде, в каком мы имеем его сейчас.

Также (чтобы продолжить небольшую тираду) Интересно, почему они не добавили понятие декларативных неизменяемых типов и не сделали это возможным ограничением универсального типа, потому что это позволило бы убедиться, что ключ не изменяет свой хэш-код во время выполнения (что может произойти в настоящее время, если реализовать GetHashCode() и Equals() на каком-то изменяемом объекте).

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