2010-07-28 1 views
3

Написав еще один вопрос для SO, я пришел к шаблону, который я использую очень часто, и я никогда не задумывался о нем. Но теперь я не уверен, что это правильный путь:Хорошая практика - вернуть IEnumerable <T> для коллекции, которая реализует INotifyCollectionChanged

Если у меня есть коллекции, с которыми мои WPF-элементы управления свяжутся, я почти всегда возвращал IEnumerable<SomeType>. Однако внутренне это в большинстве случаев ReadOnlyObservableCollection<SomeType>. У меня никогда не было проблем с этим, и все элементы управления потреблением всегда обновлялись правильно, что не удивительно, потому что они проверяют интерфейс INotifyCollectionChanged.

Но мой вопрос сейчас, если это плохая практика, объявить в подписи только IEnumerable<SomeType>, но вернуть (и также зависеть) нечто гораздо более мощное (INotifyCollectionChanged).

Update:

Я пытаюсь уточнить:

Моя главная цель заключается вернуть IEnumerable<SomeType>. Но большую часть времени возвращенный IEnumerable<SomeType> реализует также INotifyCollectionChanged, такой как ReadOnlyObservableCollection<SomeType>. Элементы управления потреблением связаны соответственно (каково мое второе намерение).

Возможно, я должен был спросить: есть ли интерфейс, который точно содержит IEnumerable и INotifyPropertyChanged.

+0

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

+0

Я хорошо понял вопрос. Я часто делаю то же самое со списком <>. – Marcel

+0

Очень поздно, но я делал это много лет, но сегодня наткнулся на случай, когда он сломал его: - У меня есть свойство, объявленное как IEnumerable , при поддержке ObservableCollection . Странно, связанный элемент управления (сетка данных) не замечает, когда элементы добавляются в коллекцию, поэтому, по-видимому, они не получают уведомления. –

ответ

4

Помните, что IEnumerable<T> и INotifyCollectionChanged - оба интерфейса - они не являются окончательным типом. Вы можете создать свой конкретный класс для реализации обоих, без проблем. Ваш API может вернуть соответствующий интерфейс для вызова метода. Это, по сути, хороший дизайн - не то, чего следует избегать.

ObservableCollection<T> делает это (косвенно через Collection<T>), а также реализует IList<T>, а также другие интерфейсы.

Если вы делаете свой собственный сбор, и планируют использовать его с привязкой к данным, я бы его реализовать IEnumerable<T> (или потенциально IList<T>, в случае необходимости) и INotifyCollectionChanged. Это даст ему лучшее удобство, как от кода, так и для эффективного связывания.


(а также зависят от)

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

Это, как говорится, я часто делаю то, что вы пытаетесь, но это не «жесткая» зависимость. Вместо этого я использую IEnumerable<T>, а проверю наINotifyCollectionChanged - воспользовавшись им, если он будет реализован. Однако я допускаю, чтобы код работал, если «вторичный» интерфейс не существует.

2

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

Однако в зависимости от того, что не гарантируется интерфейсом, это плохая практика. Если в один прекрасный день вы не получите ObservableCollection, а какой-то другой тип коллекции, тогда код будет работать не во время выполнения, а во время компиляции.

2

я склонен думать, что, если только INotifyCollectionChanged правильно, вы не хотите, чтобы вернуться просто IEnumerable Это было бы очень похоже на возвращение Object где то, что вы действительно хотите MemoryStream. Конечно, вы можете преобразовать обратно к типу вам нужно, но что, если кто-то появится позже, посмотрите тип возврата IEnumerable и напишите код, который соответствует этому возврату, но не реализует INotifyCollectionChanged?

1

Забудьте о привязке данных WPF, а затем укажите, что лучше всего подходит для возврата, IEnumerable<T> или более типа конкретов. Поскольку WPF использует рефлексию для определения наилучшего способа привязки к указанной коллекции, вы не должны беспокоиться о ней.

+0

+1 Хорошая точка. Но основным сценарием является WPF-VM (его не в моих BOs), поэтому я думаю, что я не должен забывать. Но в первой версии моего сообщения я не упоминал об этом, и если WPF будет только одним из многих сценариев или если он будет в BO, я нахожу ваш ответ действительно хорошим. – HCL

0

если это плохая практика, чтобы объявить в подписи только IEnumerable<SomeType>, но возвращаться (а также в зависимости от) чего-то гораздо более мощный (INotifyCollectionChanged)

Тип возвращаемого значения выбирается, чтобы чтобы потребители работали со стоимостью без использования небезопасного типа.

  1. Если IEnumerable возвращается то значение потребитель не должен делать предположения, является ли это собрание или это коллекция, которая может изменить или это коллекция, которая может измениться, и может сообщить о его изменениях.

Единственный способ использования IEnumerable - перечислить его! Невозможно определить, что что-то меняется, и оно должно быть перечислино снова!

  1. Если возвращается ReadOnlyObservableCollection, тогда потребитель по цене может предположить, что это коллекция, и он может уведомлять об изменениях.

ReadOnlyObservableCollection Значение потребитель может перечислить коллекцию или подписаться на уведомления об изменениях, а затем снова перечислить сбор при получении уведомления.

Полезная информация: вернуть сложную коллекцию под IEnumerable интерфейс.

Это плохая практика, чтобы использоватьIEnumerable в INotifyPropertyChanged или конвертироватьIEnumerable в INotifyPropertyChanged или что-то более сложное.

Есть интерфейс, который точно содержит IEnumerable и INotifyPropertyChanged

К сожалению, нет такого интерфейса, только класс ReadOnlyObservableCollection.

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