Intereting Posts
ComboBox items.count не соответствует datasource (C #) Как читать данные из json на C # Как я могу разблокировать файл, который заблокирован процессом в .NET Как заставить Angular JS работать в решении Visual Studio 2015? Совет по архитектуре C #: метод кэширования данных в структуре? Как отобразить имя атрибута отображения enum Указание типа возврата абстрактного метода из базового classа в соответствии с подclassом Почему мои успешно прочитанные данные Npgsql исчезают? Ядро ASP.NET, изменение перенаправления по умолчанию для несанкционированного доступа Что означает нулевой объект? Как использовать две разные сборки Microsoft Interop в одном проекте? Сохранение объектов в IsolatedStorageSettings Возврат SAFEARRAY из c ++ в c # Как установить свойство Поддерживаемые ориентации в Windows Phone 8.1 Как решить «Должен быть MarshalByRefObject» в хорошем, но множественном наследовании ампутационном языке, таком как C #?

Существует ли стандартный C ++ эквивалент IEnumerable в C #?

Или безопасно использовать вектор, если Enumerator of T просто перечисляет все элементы?

Он не нужен в C ++, и вот почему:

C # поддерживает только динамический polymorphism. Поэтому для создания алгоритма многократного использования вам нужен интерфейс, который будет реализован всеми iteratorами. Это IEnumerator , а IEnumerable – это фабрика для возврата iteratorа.

С другой стороны, шаблоны C ++ поддерживают печать утинов. Это означает, что вам не нужно ограничивать общий тип параметра интерфейсом для доступа к членам – компилятор будет искать членов по имени для каждого индивидуального экземпляра шаблона.

Контейнеры C ++ и iteratorы имеют неявные интерфейсы, которые эквивалентны .NET IEnumerable , IEnumerator , ICollection , IList , а именно:

Для контейнеров:

  • iterator и const_iterator typedefs
  • begin() member function – заполняет потребность в IEnumerable::GetEnumerator()
  • end() – вместо IEnumerator::MoveNext() возвращаемое значение

Для форвардных iteratorов:

  • value_type typedef
  • operator++ – вместо IEnumerator::MoveNext()
  • operator* и operator-> – вместо IEnumerator::Current
  • ссылочный тип возврата от operator* – вместо IList установщик индексатора
  • operator== и operator!= – нет истинного эквивалента в .NET, но с end() контейнера end() соответствует IEnumerator::MoveNext() возвращаемое значение

Для iteratorов с произвольным доступом:

  • operator+ , operator- , operator[] – вместо IList

Если вы их определите, тогда стандартные алгоритмы будут работать с вашим контейнером и iteratorом. Интерфейс не требуется, никаких виртуальных функций не требуется. Не использование виртуальных функций делает C ++ общий код быстрее, чем эквивалентный код .NET, иногда намного быстрее.


Примечание: при написании общих алгоритмов лучше использовать std::begin(container) и std::end(container) вместо функций-членов контейнера. Это позволяет использовать ваш алгоритм с необработанными массивами (которые не имеют функций-членов) в дополнение к контейнерам STL. Исходные массивы и необработанные указатели удовлетворяют всем остальным требованиям контейнеров и iteratorов с этим единственным исключением.

Стандартный C ++ способ состоит в том, чтобы передать два iteratorа:

 template void some_function(ForwardIterator begin, ForwardIterator end) { for (; begin != end; ++begin) { do_something_with(*begin); } } 

Пример кода клиента:

 std::vector vec = {2, 3, 5, 7, 11, 13, 17, 19}; some_function(vec.begin(), vec.end()); std::list lst = {2, 3, 5, 7, 11, 13, 17, 19}; some_function(lst.begin(), lst.end()); int arr[] = {2, 3, 5, 7, 11, 13, 17, 19}; some_function(arr + 0, arr + 8); 

Yay Generic программирования!

IEnumerable концептуально отличается от vector .

IEnumerable обеспечивает прямой доступ только для чтения к последовательности объектов, независимо от того, какой контейнер (если есть) содержит объекты. vector фактически является контейнером.

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

Хорошим примером является определение C ++ STL для накопления , которое можно сравнить с IEnumerable .Aggregate

В C ++

  int GetProduct(const vector& v) { // We don't provide the container, but two iterators return std::accumulate(v.begin(), v.end(), 1, multiplies()); } 

В C #

  int GetProduct(IEnumerable v) { v.Aggregate(1, (l, r) => l*r); } 

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

Я совершенно не согласен с тем, что «это не нужно», просто разные версии стандартных библиотек C ++ и .NET. Главная особенность IEnumerable <> заключается в том, что она является полиморфной, и поэтому она позволяет вызывающему пользователю использовать любой класс, который он хочет (массив, список, набор и т. Д.), Сохраняя при этом сильную типизацию при компиляции, отказоустойчивую даже в библиотеке apis ,

Единственная альтернатива в C ++ – это шаблоны. Но шаблоны C ++ не содержат безопасных типизированных дженериков во время выполнения, они в основном являются макросами. Итак, в первую очередь с шаблонами на C ++ вы вынуждены предоставить весь исходный код шаблона тем, кто должен использовать ваш шаблон. Более того, если вы создадите свою библиотеку api templated, вы потеряете возможность гарантировать, что вызов на нее будет скомпилирован, а код не будет автоматически самодокументироваться.

Я полностью сочувствую любому другому программисту, который использует C # и C ++ и разочарован этим моментом. На мой взгляд, iteratorы std уступают дизайну по сравнению с более современными идеями. Производительность вряд ли является аргументом, если я этого хочу, я всегда мог использовать необработанные указатели; особенно потому, что iteratorы – это немного больше, чем тонко обернутые указатели. Попробуйте удалить ссылку на iterator, который происходит во время выполнения до == .end (), потому что вы забыли проверить, и вы получите недопустимую ссылку – даже если вся идея дизайна C ++, избыточно вводившая ссылки, помимо указателей C, была что первые якобы гарантированно были недействительными или недействительными.