2010-04-27 1 views

ответ

9

IEnumerable не упорядоченное множество.
Хотя большинство IEnumerables заказаны, некоторые (например, Dictionary или HashSet) не являются.

Следовательно, LINQ не имеет метода IndexOf.

Однако, вы можете написать его самостоятельно:

///<summary>Finds the index of the first item matching an expression in an enumerable.</summary> 
///<param name="items">The enumerable to search.</param> 
///<param name="predicate">The expression to test the items against.</param> 
///<returns>The index of the first matching item, or -1 if no items match.</returns> 
public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate) { 
    if (items == null) throw new ArgumentNullException("items"); 
    if (predicate == null) throw new ArgumentNullException("predicate"); 

    int retVal = 0; 
    foreach (var item in items) { 
     if (predicate(item)) return retVal; 
     retVal++; 
    } 
    return -1; 
} 
///<summary>Finds the index of the first occurence of an item in an enumerable.</summary> 
///<param name="items">The enumerable to search.</param> 
///<param name="item">The item to find.</param> 
///<returns>The index of the first matching item, or -1 if the item was not found.</returns> 
public static int IndexOf<T>(this IEnumerable<T> items, T item) { return items.FindIndex(i => EqualityComparer<T>.Default.Equals(item, i)); } 
+0

Хм, но если вы говорите, что это не упорядоченный набор, не следует ли мне использовать IList, когда я хочу что-то, что должно быть заказано? Мне кажется, что использование IEnumerable, чтобы потом переделать колесо, неловко. –

+1

Да, вы должны использовать 'IList '. – SLaks

+8

Если факт, что 'IEnumerable' не всегда упорядочен, мотивирован отсутствием метода расширения IndexOf', то почему у нас есть' ElementAt'? – Trillian

1

Обратите внимание, что не может быть какой-либо метод экземпляра, потому что IEnumerable ковариантен.

Все, что угодно типа IEnumerable<string> должно быть выполнено IndexOf(string x), и, из-за ковариации, можно отливать до IEnumerable<object>.

Так что теперь выставляет в IndexOf(object x), что на самом деле IndexOf(string x), и так как не все objects являются strings, не может работать на всех объектах.

IList может сделать это, потому что он является инвариантным, то есть вы не можете наложить IList<string> на номер IList<object>.