Реализация собственного LINQ & amp; IEnumerable & л; Т & GT; [закрыто]

StackOverflow https://stackoverflow.com/questions/1230056

Вопрос

В проекте, над которым я работаю, есть действительно огромные коллекции (элементы 1M-1B), и вещи в основном модифицируются как коллекции.

Это приложение реального времени, поэтому производительность имеет первостепенное значение.

Некоторые операции, такие как Reverse, BinarySearch (возможно?) и т. д., пострадают больше, чем другие, такие как Select и т. д.

Реально ли реализовать собственный IEnumerable с возможными MoveNext, MovePrev и т. д. и собственными реализованными расширениями LINQ, которые используют их преимущества?

Если это произойдет, это произойдет в конце проекта. Потому что сначала нам нужно заставить его работать, а затем сделать его быстрее.

В целом, это не должно быть слишком много работы, верно?

Это было полезно?

Решение

Совершенно определенно возможно создать собственную реализацию Enumerable , которая может в некоторых случаях иметь особый случай. В основном вы хотите определить свои собственные типы коллекций (или, возможно, просто коллекции, такие как List < T > ) и использовать более эффективную реализацию, где это применимо.

У меня есть пример проекта , который я использовал для демонстрации " реализации LINQ to Objects в час & Quot; которые вы могли бы посмотреть на примеры. Это не полная реализация, и, в частности, она менее эффективна, чем реальная LINQ to Objects - но вы все равно можете найти ее интересной.

Кроме того, вы можете обнаружить, что i4o (Indexed LINQ) делает все необходимое из коробки - или что вам лучше внести свой вклад, чем начинать с нуля. Стоит проверить.

Просто помните, что в конечном итоге LINQ - это в основном хороший дизайн в сочетании с синтаксическим сахаром. Компилятор C #, например, не знает ничего специального о System.Linq.Enumerable .

Другие советы

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

var result = from element in collection
             where element.Id == id
             select element;

Компилируется как:

var result = collection.Where(element => element.Id == id);

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

public IEnumerable<TElement> Where(Expression<Func<TElement, bool>> selector)
{
    // detect equality of the Id member and return some special value
}

Рассмотрим System.Linq.Enumerable.Reverse () - этот метод полностью перечисляет IEnumerable перед возвратом первого результата.

Если ваш запрос myCollection.Reverse (). Take (10), а ваша коллекция содержит миллиарды элементов, ужасно было бы перечислить миллиарды элементов, чтобы получить 10.

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

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

  

Реально ли реализовать свое   IEnumerable с возможным MoveNext,   MovePrev и т. Д. И собственный реализованный LINQ   расширения, которые используют преимущества   они?

IEnumerable (или, точнее, IEnumerator ) не имеет MovePrev . Вы можете определить интерфейс:

public interface IReversable<T> : IEnumerable<T>
{
    IEnumerator<T> GetReverseEnumerator();
}

Это может быть реализовано любым контейнером, который поддерживает эффективное обратное перечисление.

Затем вы могли бы написать перегрузку Reverse (метод расширения) для работы с этим новым интерфейсом, а также для классов коллекции, которые реализуют интерфейс, и т. д. И затем вам придется использовать эту коллекцию классы вместо стандартных, таких как List < T > .

Но (у меня нет удобной для проверки Reflector), возможно, встроенный Reverse достаточно умен, чтобы делать все быстро, если он может получить IList < Интерфейс / code> из коллекции, который в любом случае прекрасно оптимизировал бы наиболее распространенные случаи.

Так что в таком подходе может быть не так много смысла.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top