Зачем нужны пользовательские коллекции и счетчики? - PullRequest
0 голосов
/ 21 октября 2009

Зачем нам нужен пользовательский набор и пользовательское перечисление путем реализации IEnumerable и IEnumerator (я знаю, что делают IEnumerable и IEnumerator и как их реализовать). Вопрос в том, что все можно сделать с такими коллекциями, как Dictionary, Hashtable, List. Так почему же мы используем собственное перечисление для создания не перечисляемых элементов в перечислимых коллекциях?

Почти все объекты ASP.NET перечислимы, как string[], int[], тогда почему я должен полагаться на свою собственную логику для перечисления?

Ответы [ 5 ]

2 голосов
/ 21 октября 2009

Самое интересное в этих интерфейсах состоит в том, что у вас могут быть классы со свойствами этого типа:

public class Customer
{
    public IEnumerable<Order> orders { get; set; }
}

(или IList<Order>). Это гораздо интереснее, чем использование List, что может стать проблемой, если вы захотите изменить его тип, и многие другие коды используют это свойство.

1 голос
/ 21 октября 2009

Вопрос состоит из двух частей, которые связаны между собой, но не одинаковы. Сначала ответим на вторую часть, теперь, когда у нас есть синтаксис yield и множество (я люблю это слово!) Встроенных опций класса коллекции, которые вы Вы можете очень редко использовать IEnumerator или IEnumerable самостоятельно. Таким образом, в подавляющем большинстве случаев пользовательский класс коллекции не должен реализовывать IEnumerable и сам IEnumerator, он должен быть производным от одного из существующих встроенных классов коллекции, который уже делает это для вас.

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

   public Invoices: List<Invoice>
   {
        public Invoices OverDueInvoices 
        { get {return this.Where( i => i.IsOverdue()); } }

        public Invoices InvoicesByState(string stateAbbrev)
        { return this.Where( i => i.State == stateAbbrev);  }

        public Invoice this[int invoiceId]
        { get { return this.Find( i => i.InvoiceId == invoiceId); } }

        // extra functionality as required 
   }
1 голос
/ 21 октября 2009

Вы можете реализовать IEnumerator, если перечисляемые вами объекты не происходят из простой коллекции в памяти, но вы хотите иметь возможность абстрагировать код, который фактически создает объекты, и использовать их так, как если бы они были простой массив.

Например, вы можете создать класс FileEnumerator, который реализует IEnumerator<string> и читает следующую строку файла каждый раз, когда вызывается MoveNext. Затем вы можете прочитать файл, как если бы он был массивом строк, без необходимости хранить весь файл в памяти.

0 голосов
/ 21 октября 2009

Мне было бы трудно найти причину, чтобы написать список клиентов. При необходимости существует так много способов создания коллекций IEnumerable на лету. Помимо возможности LINQ генерировать новые коллекции по требованию, существуют также методы, реализованные в неуниверсальных коллекциях, таких как AsEnumerable (), OfType и Cast, которые будут создавать универсальные перечисления из неуниверсальных коллекций.

Как указывает Питер, интерфейсы обеспечивают более гибкую связь между классами, но это не требует написания пользовательских классов. List реализует IEnumerable, поэтому присвоение List его свойству "orders" отвечает потребностям интерфейса.

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

0 голосов
/ 21 октября 2009

Обобщения достаточно мощные, поэтому у меня не было необходимости писать новый класс, который реализует IEnumerable и IEnumerator в течение длительного времени. В тех случаях, когда мне нужны некоторые пользовательские функции в моих коллекциях, я мог наследовать от List или Dictionary, а не реализовывать эти интерфейсы самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...