2009-10-09 3 views
11

Каковы рекомендации по экспорту пользовательской коллекции и общей? Custom Collection vs Generic Collection для общедоступных методов

например
public class ImageCollection : Collection<Image> 
{ 
    ... 
} 

public class Product 
{ 
    public ImageCollection {get; set;} 
} 

VS

public class Product 
{ 
    public Collection<Image> Images{get; set;} 
} 

Какие дела вы бы рассмотреть вопрос о создании пользовательской коллекции? Каковы преимущества и недостатки каждого метода?

+1

Третьей возможностью было бы разоблачить IList of Image. –

+0

В совокупности я имею в виду IList, List и т. Д., Когда я говорю «Коллекция». Я думаю, что этот вопрос по-прежнему применяется, даже если его для списка или IList и т. Д. – 2009-10-09 16:49:07

+0

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

ответ

9

В общем, лучше выставить один из интерфейсов, таких как IEnumerable<T>, ICollection<T> или IList<T> вместо конкретного класса.

Это дает вам гораздо большую гибкость с точки зрения изменения внутреннего API. IEnumerable<T>, в частности, позволяет вам позже изменить внутренние настройки, чтобы обеспечить возможность потоковой передачи результатов, поэтому является наиболее гибким.

Если вы знаете ожидаемые шаблоны использования ваших «коллекций», вы должны предоставить соответствующий API, который в будущем будет обеспечивать минимальные ограничения на вас. Если, например, вы знаете, что людям просто нужно повторять ваши результаты, выведите IEnumerable<T>, чтобы позже вы могли перейти в ЛЮБОЙ коллекцию или даже переключиться непосредственно на возврат доходности.

+0

Я думаю, что согласен с вами, используя упрощенную «коллекцию» для внутреннего api. Но не могли бы вы разоблачить IEnumerable , ICollection или IList в вашем общедоступном Api? Или вы бы создали пользовательскую «коллекцию», которая реализует IEnumerable , ICollection или IList , таким образом, охватывая описанные выше функции pros womp? – 2009-10-09 17:14:54

+4

Нет. На самом деле (сейчас) руководство по проектированию каркаса предлагает подвергать IEnumerable , IList и т. Д. В публичных API. Они дают вам максимальную гибкость для изменения внутренней реализации, не нарушая публичный API. Если вы реализуете пользовательскую коллекцию, вы навсегда заблокированы для этого типа, если не хотите нарушить совместимость API. –

5

Я бы пошел на второй. Клиентский код должен знать тип изображения в любом случае.

Первый означает только больше кода.

1

Единственная причина когда-либо использовать Collection<T> - это если вы хотите подключиться к набору виртуальных методов, который позволит вам увидеть все мутации в базовом списке. Это позволяет выполнять такие операции, как реагировать на удаление, осуществлять события и т. Д.

Если вы не заинтересованы в том, чтобы реагировать на эти изменения коллекции или наблюдать за ними, то более подходящим является тип List<T>.

13

Если вы создаете открытый API, рассмотрите возможность использования пользовательской коллекции для следующих преимуществ.

  • Расширяемость - вы можете добавлять функции в свою коллекцию в будущем без изменения API.

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

  • Также легче сделать потенциально разрушающие изменения с меньшим воздействием. Возможно, позже вы решите, что не хотите, чтобы он был Collection<Image>, но другой тип коллекции - вы можете адаптировать свой класс ImageCollection к тем же методам, что и раньше, но наследовать от чего-то другого - и клиентский код вряд ли удастся сломать ,

Если это только код внутреннего использования, решение не обязательно так важно, и вы можете решить, что «проще, лучше».

Примером, приведенным в моей голове, является API-интерфейс ArcGIS Server от ESRI - они используют пользовательские коллекции в своих API-интерфейсах. По этим причинам мы также используем пользовательские коллекции в наших API.

+1

Фактически, изменение базового типа класса считается нарушением изменения (например, если код клиента присваивает его «Collection »), но обычно это не имеет значения. – SLaks

+0

Я бы никогда не рекомендовал ссылаться на любой ArcGIS API в качестве примера «хорошего» .NET, которому нужно следовать. Они используют пользовательские коллекции, потому что они застряли в обертке COM, но они также используют итераторы java-стиля во всем мире в .NET api, не выставляйте IEnumerable или IEnumerable , где они должны, и многие другие настройки, которые делают жизнь очень сложной. –

+0

@Slaks - очень верно. Это все равно смягчает его. – womp

5

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

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

class Product { 
    private readonly Collection<Image> _images; 
    public Product() { _images = new Collection<Image>(); } 
    public Collection<Image> Images { get { return _images; } } 
} 

-Oisin

+2

+1 для наконечника на геттере. – 2009-10-09 16:33:36

1

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

Это обычно выглядит следующим образом:

public interface IProduct 
{ 
    ICollection<Image> Images { get; } 
} 

public class Product : IProduct 
{ 
    private class ImageCollection : Collection<Image> 
    { 
     // override InsertItem, RemoveItem, etc. 
    } 

    private readonly ImageCollection _images; 
    public ICollection<Image> Images 
    { 
     get { return _images; } 
    } 
} 

Я также часто делают пользовательский класс коллекции вложен внутри другого класса, что позволяет мне изменить некоторые частные члены родительского класса во время добавления/удаления.