Поиск коллекций; альтернатива словарю - PullRequest
2 голосов
/ 28 июня 2009

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

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

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

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

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

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

Что вы думаете?

Cheers, Berryl

Ответы [ 3 ]

3 голосов
/ 28 июня 2009

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

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

3 голосов
/ 28 июня 2009

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

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

2 голосов
/ 28 июня 2009

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

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

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

...