Antworten:
Wenn Sie LINQ verwenden können, können Sie Folgendes verwenden:
var e = enumerable.First();
Dies löst jedoch eine Ausnahme aus, wenn enumerable leer ist. In diesem Fall können Sie Folgendes verwenden:
var e = enumerable.FirstOrDefault();
FirstOrDefault()wird zurückgegeben, default(T)wenn die Aufzählung leer ist, was nullfür Referenztypen oder der Standardwert 'Nullwert' für Werttypen gilt.
Wenn Sie LINQ nicht verwenden können, ist Ihr Ansatz technisch korrekt und unterscheidet sich nicht vom Erstellen eines Enumerators mit den Methoden GetEnumeratorund MoveNextzum Abrufen des ersten Ergebnisses (in diesem Beispiel wird davon ausgegangen, dass Enumerable ein ist IEnumerable<Elem>):
Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
if (enumer.MoveNext()) e = enumer.Current;
}
Joel Coehoorn erwähnt .Single()in den Kommentaren; Dies funktioniert auch, wenn Sie erwarten, dass Ihre Aufzählung genau ein Element enthält. Es wird jedoch eine Ausnahme ausgelöst, wenn sie entweder leer oder größer als ein Element ist. Es gibt eine entsprechende SingleOrDefault()Methode, die dieses Szenario auf ähnliche Weise abdeckt wie FirstOrDefault(). Doch David B erklärt , dass SingleOrDefault()immer noch eine Ausnahme in dem Fall werfen kann , wenn die zählbaren mehr als ein Element enthält.
Bearbeiten: Vielen Dank an Marc Gravell, der darauf hingewiesen hat, dass ich mein IEnumeratorObjekt nach der Verwendung entsorgen muss. Ich habe das Nicht-LINQ-Beispiel bearbeitet, um das usingSchlüsselwort zur Implementierung dieses Musters anzuzeigen .
Nur für den Fall, dass Sie .NET 2.0 verwenden und keinen Zugriff auf LINQ haben:
static T First<T>(IEnumerable<T> items)
{
using(IEnumerator<T> iter = items.GetEnumerator())
{
iter.MoveNext();
return iter.Current;
}
}
Dies sollte das tun, wonach Sie suchen ... es werden Generika verwendet, damit Sie das erste Element für einen beliebigen IEnumerable-Typ erhalten.
Nennen Sie es so:
List<string> items = new List<string>() { "A", "B", "C", "D", "E" };
string firstItem = First<string>(items);
Oder
int[] items = new int[] { 1, 2, 3, 4, 5 };
int firstItem = First<int>(items);
Sie können es leicht genug ändern, um die IEnumerable.ElementAt () -Erweiterungsmethode von .NET 3.5 nachzuahmen:
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;
}
}
Nennen wir es so:
int[] items = { 1, 2, 3, 4, 5 };
int elemIdx = 3;
int item = ElementAt<int>(items, elemIdx);
Natürlich , wenn Sie tun Zugang zu LINQ haben, dann gibt es viele gute Antworten bereits gebucht ...
Nun, Sie haben nicht angegeben, welche Version von .Net Sie verwenden.
Angenommen, Sie haben 3.5, ist die ElementAt-Methode eine andere Möglichkeit:
var e = enumerable.ElementAt(0);
Elem e = enumerable.FirstOrDefault();
//do something with e
Verwenden Sie FirstOrDefault oder eine foreach-Schleife, wie bereits erwähnt. Das manuelle Abrufen eines Enumerators und das Aufrufen von Current sollten vermieden werden. foreach entsorgt Ihren Enumerator für Sie, wenn er IDisposable implementiert. Wenn Sie MoveNext und Current aufrufen, müssen Sie es manuell entsorgen (falls zutreffend).
Wenn Ihr IEnumerable es nicht verfügbar macht <T>und Linq fehlschlägt, können Sie eine Methode mithilfe von Reflection schreiben:
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;
}
Sie können auch die allgemeinere Version ausprobieren, die Ihnen das i-te Element gibt
enumerable.ElementAtOrDefault (i));
ich hoffe es hilft