[C#] .net의 IEnumerable <T>에서 첫 번째 요소를 얻는 방법은 무엇입니까?

나는 종종 in.net의 첫 번째 요소를 잡고 싶고 IEnumerable<T>좋은 방법을 찾지 못했습니다. 내가 생각해 낸 최선은 다음과 같습니다.

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

왝! 이렇게하는 좋은 방법이 있습니까?



답변

LINQ를 사용할 수있는 경우 다음을 사용할 수 있습니다.

var e = enumerable.First();

열거 형이 비어있는 경우 예외가 발생합니다.이 경우 다음을 사용할 수 있습니다.

var e = enumerable.FirstOrDefault();

FirstOrDefault()default(T)열거 형이 비어있는 경우 반환 됩니다.이 null형식은 참조 형식이거나 값 형식의 기본 ‘0 값’입니다.

LINQ를 사용할 수없는 경우 기술적으로 정확하고 GetEnumeratorand MoveNext메소드를 사용하여 열거자를 작성 하여 첫 번째 결과를 검색하는 것 (이 예에서는 열거 가능한 것이이라고 가정) 과 다르지 않습니다 IEnumerable<Elem>.

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

.Single()의견에 Joel Coehoorn이 언급 되었습니다. 열거 형에 정확히 하나의 요소가 포함될 것으로 예상되는 경우에도 작동합니다. 그러나 비어 있거나 하나 이상의 요소 인 경우 예외가 발생합니다. SingleOrDefault()이와 유사한 방식으로이 시나리오를 다루는 해당 방법이 있습니다 FirstOrDefault(). 그러나 David BSingleOrDefault()열거 형에 둘 이상의 항목이 포함 된 경우 여전히 예외 가 발생할 수 있다고 설명합니다 .

편집 : 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에 액세스 할 있다면 이미 게시 된 좋은 답변이 많이 있습니다 …


답변

글쎄, 사용중인 .Net 버전을 지정하지 않았습니다.

3.5가 있다고 가정하면 다른 방법은 ElementAt 메소드입니다.

var e = enumerable.ElementAt(0);


답변

FirstOrDefault ?

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


답변

이 시도

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


답변

이미 언급했듯이 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;
}