回答:
LINQを使用できる場合は、以下を使用できます。
var e = enumerable.First();
ただし、enumerableが空の場合は例外がスローされます。その場合は次のように使用できます。
var e = enumerable.FirstOrDefault();
FirstOrDefault()default(T)列挙型が空の場合に返されます。これはnull、参照型の場合、または値型のデフォルトの「ゼロ値」の場合です。
LINQを使用できない場合、アプローチは技術的に正しく、GetEnumeratorand MoveNextメソッドを使用して最初の結果を取得する列挙子を作成することと同じです(この例では、列挙可能はであると想定していますIEnumerable<Elem>)。
Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
if (enumer.MoveNext()) e = enumer.Current;
}
Joel Coehoorn.Single()がコメントで言及しました。これは、列挙可能要素に正確に1つの要素が含まれることを期待している場合にも機能します。ただし、要素が空であるか、1つの要素よりも大きい場合は、例外がスローされます。SingleOrDefault()と同様の方法でこのシナリオをカバーする対応するメソッドがありFirstOrDefault()ます。ただし、David BはSingleOrDefault()、列挙型に複数のアイテムが含まれている場合でも例外がスローされる可能性があると説明しています。
編集:使用後にオブジェクトを破棄する必要があることを指摘してくれたMarc Gravellに感謝IEnumeratorしますusing。このパターンを実装するためのキーワードを表示するように非LINQの例を編集しました。
.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にアクセスできる場合は、すでにたくさんの良い答えが投稿されています...
Elem e = enumerable.FirstOrDefault();
//do something with e
すでに述べたように、FirstOrDefaultまたはforeachループを使用します。列挙子を手動でフェッチしてCurrentを呼び出すことは避けてください。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番目の要素を与えるより一般的なバージョンを試すこともできます
enumerable.ElementAtOrDefault(i));
それが役に立てば幸い