C#: как реализовать IOrderedEnumerable
Я хочу реализовать несколько различных алгоритмов для практики, просто чтобы увидеть, насколько я действительно плох и стать лучше: p
в любом случае, я думал, что попытаюсь использовать IEnumerable<T>
и IOrderedEnumerable<T>
и другие типы коллекций .Net только для совместимости (так что то, что я пишу, можно использовать более легко позже).
но я не могу найти способ вернуть экземпляр IOrderedEnumerable<T>
кроме использования методов расширения OrderBy и ThenBy. Так что, думаю, я должен создать свой собственный класс, который реализовать этот интерфейс. Но интерфейс не совсем имеет смысл для меня, чтобы быть честным. Возможно, но я не уверен.
Я создал пустой класс, добавил интерфейс, а затем получил ReSharper для добавления пустых реализаций для меня. Выглядит это так:
class MyOrderedEnumerable<T> : IOrderedEnumerable<T>
{
/// <summary>
/// Performs a subsequent ordering on the elements of an <see cref="T:System.Linq.IOrderedEnumerable`1"/> according to a key.
/// </summary>
/// <returns>
/// An <see cref="T:System.Linq.IOrderedEnumerable`1"/> whose elements are sorted according to a key.
/// </returns>
/// <param name="keySelector">The <see cref="T:System.Func`2"/> used to extract the key for each element.</param><param name="comparer">The <see cref="T:System.Collections.Generic.IComparer`1"/> used to compare keys for placement in the returned sequence.</param><param name="descending">true to sort the elements in descending order; false to sort the elements in ascending order.</param><typeparam name="TKey">The type of the key produced by <paramref name="keySelector"/>.</typeparam><filterpriority>2</filterpriority>
public IOrderedEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending)
{
throw new NotImplementedException();
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
чего я не понимаю-это CreateOrderedEnumerable
метод. Что именно он должен делать? Ну, я предполагаю, что это, конечно, создаст упорядоченный перечисляемый, но как? Сам алгоритм сортировки должен туда входить? А что это этакое? В этом методе нет коллекции элементов, поэтому где она должна получить коллекцию на заказ? Как бы вы использовали класс? Это должно быть реализовано, например, как частный вспомогательный класс внутри чего-то, что нужно сортировать?
тогда вместо MyOrderedEnumerable<T> : IOrderedEnumerable<T>
, может быть QuickSorter<T> : IOrderedEnumerable<T>
который взял коллекцию в своем конструкторе и отсортировал ее, когда это CreateOrderedEnumerable
метод был вызван... но что будет, если кто-нибудь позвонит?--8--> и начал перечислять до того, как был вызван этот метод?
ха-ха, только что обнаружил, что я спросил что-то подобное некоторое время назад здесь. Но это было как раз то, что можно было вернуть. Поэтому я думаю, что этот вопрос является ответом на один ответ, который я получил там=)
2 ответов
у меня есть пример реализации вы могли бы посмотреть. Он не предназначен для того, чтобы быть эффективным, но он должен заставить вас начать.
в основном IOrderedEnumerable<T>
просто нужно иметь представление о его текущем порядке, чтобы он мог создать новый. Предполагая, что у вас уже есть IComparer<T>
вы строите новый, говоря что-то вроде:
int Compare(T first, T second)
{
if (baseComparer != null)
{
int baseResult = baseComparer.Compare(first, second);
if (baseResult != 0)
{
return baseResult;
}
}
TKey firstKey = keySelector(first);
TKey secondKey = keySelector(second);
return comparer.Compare(firstKey, secondKey);
}
таким образом, в основном вы создаете цепочку компараторов, идущих от " наименее значимого "до"наиболее значимого". Вам также нужно поместить туда бит" нисходящий", но это легко:)
в приведенном выше примере три разных аспекта представлены в трех разных классах, уже присутствующих в MiscUtil:
-
ReverseComparer
: меняет существующий С -
LinkedComparer
: создает один компаратор из двух, с одним мастером и одним рабом -
ProjectionComparer
: создает компаратор на основе проекции из исходных элементов к ключам, делегируя другому компаратору для сравнения этих ключей.
Comparers для сцепления вместе.
предположительно, ваш класс будет иметь некоторую внутреннюю переменную хранения, которая реализует IEnumerable
(List<T>
например). Реализация данного метода проста в таком случае:
private List<T> data = new List<T>();
public IOrderedEnumerable<CalculationResult> CreateOrderedEnumerable<TKey>(Func<CalculationResult, TKey> keySelector, IComparer<TKey> comparer, bool descending)
{
return descending ?
data.OrderByDescending(keySelector, comparer)
: data.OrderBy(keySelector, comparer);
}