[英]How do I get the first element from an IEnumerable<T> in .net?
我经常想在.net中获取IEnumerable<T>
的第一个元素,我还没有找到一个很好的方法来做到这一点。 我提出的最好的是:
foreach(Elem e in enumerable) {
// do something with e
break;
}
呸! 那么,有一个很好的方法来做到这一点?
如果你可以使用LINQ,你可以使用:
var e = enumerable.First();
如果enumerable为空,这将抛出异常:在这种情况下,您可以使用:
var e = enumerable.FirstOrDefault();
如果枚举为空,则FirstOrDefault()
将返回default(T)
,对于引用类型,它将为null
,对于值类型,默认为“零值”。
如果你不能使用LINQ,那么你的方法在技术上是正确的,与使用GetEnumerator
和MoveNext
方法创建枚举器来检索第一个结果没有区别(这个例子假设enumerable是一个IEnumerable<Elem>
):
Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
if (enumer.MoveNext()) e = enumer.Current;
}
Joel Coehoorn在评论中提到.Single()
; 如果你期望你的枚举只包含一个元素,那么它也会起作用 - 但如果它是空的或大于一个元素,它将抛出异常。 有相应SingleOrDefault()
其覆盖该场景以类似的方式,以方法FirstOrDefault()
但是, David B解释说,在可枚举包含多个项目的情况下, SingleOrDefault()
仍可能抛出异常。
编辑:感谢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;
}
}
这应该做你正在寻找的...它使用泛型,所以你得到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);
Elem e = enumerable.FirstOrDefault();
//do something with e
如果您的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;
}
试试这个
IEnumberable<string> aa;
string a = (from t in aa where t.Equals("") select t.Value).ToArray()[0];
您还可以尝试更通用的版本,它会为您提供第i个元素
enumerable.ElementAtOrDefault(I));
希望能帮助到你
如前所述,使用FirstOrDefault或foreach循环。 应该避免手动获取枚举器并调用Current。 如果它实现IDisposable,foreach将为您处置您的枚举器。 调用MoveNext和Current时,必须手动处理它(如果适用)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.