2012-02-16 4 views
0

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

У меня есть элемент управления, который работает на структуры, как:

IDictionary<string, IDictionary<string, IEnumerable<MyObject>>> 

Так что поставки два ключа, мы получаем коллекцию объектов обратно. Довольно прямо.

У меня есть класс

ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue> 

, который только что, только для чтения словарь, так что любые IDictionary методы, которые могли бы изменить словарь бросить NotSupportedException();

Словарь на котором работает управление выходит из MyObjectRepository, который возвращает

ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<MyObject>>> 

Таким образом, вопрос, следует ли обновить тип возвращаемого на моем хранилище, чтобы вернуть

IDictionary<string, IDictionary<string, IEnumerable<MyObject>>> 

или ...? Я не думаю, что было бы правильно обновить метод, чтобы взять словарь для чтения, поскольку это излишне ограничивает.

Кажется, что это делает его менее понятным относительно типа возврата. Кроме того, интерфейс определяет ReadOnlyDictionary как возвращаемый тип, так что реализующие классы не могут возвращать словари, которые позволяли бы изменять. Просто кажется, что если интерфейс возвращает коллекцию, которая должна быть только прочитана, то тип возврата должен отражать это. Указав общий IDictionary < ...> тип возвращаемого значения, методы, которые используют интерфейс, могут попытаться изменить словарь только для выполнения исключения NotSupportedException.

Любые предложения о том, как разрешить это, оцениваются!

ОБНОВЛЕНИЕ Как оказалось, реальная проблема здесь с ReadOnlyCollection. Он просто должен быть заменен IEnumerable и упрощает большую часть работы, конвертируя различные типы возвращаемых данных.

См. ReadOnlyCollection or IEnumerable for exposing member collections? и обратите внимание на ответ Джона Скита. Вот почему я люблю так :)

ответ

1

Моим наклонением было бы определить интерфейсы: DoubleKeyLookup<out ValT>, и полученное от этого, DoubleKeyLookup<in KeyT1, in KeyT2, out ValT>. У первого были бы такие методы, как GetSequence(Object key1, Object key2);, TryGetSequence и GetSequenceOrEmpty (первый бы бросил на не найденный, второй вернул null, третий вернул Enumerable<ValT>.Empty). Второй будет аналогичным, но с «ключевыми» параметрами указанных типов. Большинство потребителей, вероятно, будут использовать второе, но первое будет пригодно для использования в случае, если вы хотите, например, см., если конкретный Animal был в словаре, где все ключи были Cat.

+0

Мне нравится гибкость этого ответа, и он, похоже, следует за linq, где у нас есть метод, который будет выдавать, тот, который возвращает null, и тот, который возвращает пустой. Спасибо за идею – MPavlak

1

Самый простой и удобный способ, которым я могу думать:

С ReadOnlyDictionary реализует IDictionary <,> но бросает исключения на неподдерживаемых операций, я рекомендовал бы, что самый простой и наиболее читаемым способом является возвращение ReadOnlyDictionary <,> который реализует IReadOnlyDictionary <,> вместо этого. IReadOnlyDictionary <,> просто выводится из IDictionary <,> поскольку они функционально эквивалентны.

Имя «IReadonlyDictionary» в прототипе метода затем указывает вызывающему, что методы, которые изменяют словарь, могут не работать.

Надеюсь, это поможет!

+0

Мне нравятся оба предоставленных ответа и, вероятно, используйте это для более простых проектов. – MPavlak

Смежные вопросы