Answers:
如果可以使用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
如前所述,使用FirstOrDefault或foreach循环。应避免手动获取枚举数并调用Current。如果实现IDisposable,则foreach将为您处理枚举数。调用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;
}