Відповіді:
Якщо ви можете використовувати LINQ, ви можете використовувати:
var e = enumerable.First();
Це викине виняток, хоча якщо номер порожній: у такому випадку ви можете використовувати:
var e = enumerable.FirstOrDefault();
FirstOrDefault()повернеться, default(T)якщо нумерація буде порожньою, що буде nullдля посилальних типів або за нульовим значенням для типів значень.
Якщо ви не можете використовувати LINQ, ваш підхід є технічно правильним і не відрізняється від створення перелічувача з використанням методів GetEnumeratorі MoveNextдля отримання першого результату (цей приклад передбачає, що численні є IEnumerable<Elem>):
Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
if (enumer.MoveNext()) e = enumer.Current;
}
Джоель Куехорн, згаданий .Single()у коментарях; це також спрацює, якщо ви очікуєте, що ваш номер містить точно один елемент - однак він викине виняток, якщо він порожній або більший, ніж один елемент. Існує відповідний SingleOrDefault()метод, який охоплює цей сценарій аналогічним чином FirstOrDefault(). Однак Девід Б пояснює, що SingleOrDefault()все-таки може бути винятком випадок у тому випадку, коли перелік містить більше одного елемента.
Редагувати: Дякую Марку Гравеллу за те, що він зазначив, що мені потрібно розпоряджатися своїм IEnumeratorоб’єктом після його використання - я відредагував приклад, який не є LINQ, щоб відобразити usingключове слово для реалізації цього шаблону.
На випадок, якщо ви використовуєте .NET 2.0 і не маєте доступу до LINQ:
static T First<T>(IEnumerable<T> items)
{
using(IEnumerator<T> iter = items.GetEnumerator())
{
iter.MoveNext();
return iter.Current;
}
}
Це має робити те, що ви шукаєте ... він використовує дженерики, щоб ви отримали перший предмет будь-якого типу IEnumerable.
Назвіть це так:
List<string> items = new List<string>() { "A", "B", "C", "D", "E" };
string firstItem = First<string>(items);
Або
int[] items = new int[] { 1, 2, 3, 4, 5 };
int firstItem = First<int>(items);
Ви можете легко змінити його, щоб імітувати метод розширення IEnumerable.ElementAt () .NET 3.5:
static T ElementAt<T>(IEnumerable<T> items, int index)
{
using(IEnumerator<T> iter = items.GetEnumerator())
{
for (int i = 0; i <= index; i++, iter.MoveNext()) ;
return iter.Current;
}
}
Називаючи це так:
int[] items = { 1, 2, 3, 4, 5 };
int elemIdx = 3;
int item = ElementAt<int>(items, elemIdx);
Звичайно , якщо ви робите мати доступ до LINQ, тобто багато хороших відповідей вже відповідав ...
Ну, ви не вказали, яку версію .Net використовуєте.
Якщо припустити, що у вас є 3.5, інший спосіб - метод ElementAt:
var e = enumerable.ElementAt(0);
Elem e = enumerable.FirstOrDefault();
//do something with e
Використовуйте FirstOrDefault або цикл foreach, як уже згадувалося. Слід уникати ручного вибору перелічувача та виклику струму. foreach розпоряджається вашим перерахувачем, якщо він реалізує IDisposable. Під час виклику MoveNext і Current ви повинні розпоряджатися ним вручну (якщо це можливо).
Якщо ваш IEnumerable не демонструє це, <T>а Linq виходить з ладу, ви можете написати метод, використовуючи відображення:
public static T GetEnumeratedItem<T>(Object items, int index) where T : class
{
T item = null;
if (items != null)
{
System.Reflection.MethodInfo mi = items.GetType()
.GetMethod("GetEnumerator");
if (mi != null)
{
object o = mi.Invoke(items, null);
if (o != null)
{
System.Reflection.MethodInfo mn = o.GetType()
.GetMethod("MoveNext");
if (mn != null)
{
object next = mn.Invoke(o, null);
while (next != null && next.ToString() == "True")
{
if (index < 1)
{
System.Reflection.PropertyInfo pi = o
.GetType().GetProperty("Current");
if (pi != null) item = pi
.GetValue(o, null) as T;
break;
}
index--;
}
}
}
}
}
return item;
}
ви також можете спробувати більш загальну версію, яка дає вам i-й елемент
перелічувальний.ElementAtOrDefault (i));
сподіваюся, що це допомагає