如何从.net中的IEnumerable <T>获取第一个元素?

我经常想抓取.net中IEnumerable<T>的第一个元素,但是我还没有find一个好办法。 我想到的最好的是:

 foreach(Elem e in enumerable) { // do something with e break; } 

呸! 那么,有没有一个很好的方法来做到这一点?

如果你可以使用LINQ,你可以使用:

 var e = enumerable.First(); 

这将抛出一个exception,虽然如果可枚举是空的:在这种情况下,你可以使用:

 var e = enumerable.FirstOrDefault(); 

FirstOrDefault()将返回default(T)如果可枚举为空,对于引用types或值types的默认“零值”将为null

如果你不能使用LINQ,那么你的方法在技术上是正确的,与使用GetEnumeratorMoveNext方法创build一个枚举器来获取第一个结果(这个例子假设枚举是一个IEnumerable<Elem> )没有什么不同:

 Elem e = myDefault; using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) { if (enumer.MoveNext()) e = enumer.Current; } 

Joel Coehoorn在评论中提到.Single() 这也可以,如果你期望你的枚举只包含一个元素 – 但是它会抛出一个exception,如果它是空的或大于一个元素。 有一个对应的SingleOrDefault()方法,它和FirstOrDefault()类似。 但是, 大卫B解释SingleOrDefault()可能仍然抛出一个exception的情况下,可枚举包含多个项目。

编辑:感谢Marc Gravell指出,我需要在使用它之后处理我的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; } } 

这应该做你正在寻找…它使用generics,所以你得到任何types的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); 

你可以修改它足够模仿.NET 3.5的IEnumerable.ElementAt()扩展方法:

 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); 

FirstOrDefault ?

 Elem e = enumerable.FirstOrDefault(); //do something with e 

如前所述,使用FirstOrDefault或foreach循环。 应避免手动提取枚举器并调用Current。 如果它实现了IDisposable,foreach会为你configuration你的枚举器。 当调用MoveNext和Current时,您必须手动处理(如果适用)。

如果你的IEnumerable没有公开它的<T>并且Linq失败了,你可以使用reflection来写一个方法:

 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; } 

尝试这个

 IEnumberable<string> aa; string a = (from t in aa where t.Equals("") select t.Value).ToArray()[0]; 

你也可以尝试更通用的版本给你的第i个元素

enumerable.ElementAtOrDefault(I));

希望能帮助到你