Есть ли интерфейс, который указывает, что аргумент (коллекция) может быть проиндексирован целым числом? - PullRequest
1 голос
/ 27 октября 2011

Я пытаюсь использовать OrderedDictionary в качестве аргумента для функции расширения ниже (кстати, если вы думаете, collection.Reverse().Where(i => predicate(i)).Take(n) было бы лучше, дайте мне знать!), Но я использую общую реализацию OrderedDictionary (основанную на эта версия ) не поддерживает IList.

Коллекция должна предоставлять доступ к своим элементам только с помощью целочисленного индекса (что делает OrderedDictionary).

Есть ли другой способ указать это требование, не создавая перегрузки?

/// <summary>
/// Return n elements, starting from the end of collection, that satisfy predicate.
/// </summary>
/// <param name="collection"></param>
/// <param name="predicate"></param>
/// <param name="n">Max number of elements to return</param>
/// <returns></returns>
public static IEnumerable<T> LastBefore<T>(this IList<T> collection, Func<T, bool> predicate, int n) {
    if (collection == null) 
    {
        throw new ArgumentNullException("collection");
    }
    for (int i = collection.Count - 1; i >= 0; i--) 
    {
        if (n == 0) break;
        if (predicate(collection[i])) 
        {
            --n;
            yield return collection[i];
        }
    }
}

Ответы [ 3 ]

1 голос
/ 27 октября 2011

Я бы предложил определить интерфейс IReadableList; если бы не тот факт, что индексатор чтения-записи не считается реализацией индексатора только для чтения, такая вещь могла бы быть родителем IList (IMHO, так должно было быть в любом случае). Существующие реализации IList не будут реализовывать IReadableList, если не заключить в оболочку, увы, но наличие интерфейса списка только для чтения сделало бы концепцию ковариации гораздо более полезной, поскольку IReadableList можно использовать в качестве IReadableList .

Кстати, я склонен думать, что хотя IList не наследуется от неуниверсального IList, возможно, так и должно быть. Любой IList может реализовать IList безопасным для типов способом, если неуниверсальная реализация доступна только для чтения. Даже если вы никогда не прочитаете какие-либо объекты из неуниверсального IList, его реализация позволит запустить подпрограмму, которая хочет IEnumerable , но получает IList [который, конечно, реализует IEnumerable , и, следовательно, неявно IEnumerable ], чтобы получить Count коллекции, не перечисляя ее.

1 голос
/ 27 октября 2011

Согласно в MSDN об ограничениях типов , к сожалению, нет.

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

0 голосов
/ 27 октября 2011

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

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

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