c# foreach 사용법




IEnumerable foreach, 마지막 요소에 대해 다른 작업 수행 (4)

IEnumerable<T> 있습니다. 마지막 항목을 제외하고 컬렉션의 각 항목에 대해 하나의 작업을 수행하고 싶습니다. 다른 작업을 수행하고 싶습니다. 어떻게 이것을 깔끔하게 코드화 할 수 있습니까? 의사 코드

foreach (var item in collection)
{
    if ( final )
    {
        g(item)
    }
    else
    {
        f(item)
    }
}

그래서 내 IEnumerable가 Enumerable.Range(1,4) 였다면 f (1) f (2) f (3) g (4)를 할 것입니다. NB. 내 IEnumerable 길이가 1 일 경우, 나는 g (1) 싶어요.

내 IEnumerable은 일종의 엉터리인데 Count() 는 모든 것을 반복하는 것만큼 비싸다.


100 % 확신 할 수는 없지만, IEnumerable 배열로 한 단계 이동하기 전까지는 항목 사용을 항상 지연시킬 수 있습니다. 이렇게하면 마지막 항목을 사용하지 않아도됩니다.

그것은 열거자를 세지 않아도되는 것을 피합니다.

object item = null;
foreach (var a in items)
{
  // if item is set then we can use it.
  if (item != null)
  {
      // not final item
      f(item);
  }
  item = a;
}

// final item.
g(item);

Marc의 답변과 비슷하지만이를 마무리 할 확장 메서드를 작성할 수 있습니다.

public static class LastEnumerator
{
    public static IEnumerable<MetaEnumerableItem<T>> GetLastEnumerable<T>(this IEnumerable<T> blah)
    {
        bool isFirst = true;
        using (var enumerator = blah.GetEnumerator())
        {
            if (enumerator.MoveNext())
            {
                bool isLast;
                do
                {
                    var current = enumerator.Current;
                    isLast = !enumerator.MoveNext();
                    yield return new MetaEnumerableItem<T>
                        {
                            Value = current,
                            IsLast = isLast,
                            IsFirst = isFirst
                        };
                    isFirst = false;
                } while (!isLast);
            }
        }

    }
}

public class MetaEnumerableItem<T>
{
    public T Value { get; set; }
    public bool IsLast { get; set; }
    public bool IsFirst { get; set; }
}

다음과 같이 호출하십시오.

foreach (var row in records.GetLastEnumerable())
{
    output(row.Value);
    if(row.IsLast)
    {
        outputLastStuff(row.Value);
    }
}

나는 정말로 그것을 권하고 싶지는 않지만, 당신이 이렇게 할 수 있다고 생각합니다 ...

object m_item = notPartOfListFlag = new object();
foreach(var item in enumerator){
   if(m_item != notPartOfListFlag)
   {
      //do stuff to m_item;
   }
   m_item = item;
}
//do stuff to last item aka m_item;

하지만 목록에있는 항목의 위치를 ​​노출하는 컬렉션을 사용하려고합니다.

if(collection.IndexOf(item) == collection.Count-1) do stuff

IList[<T>] 아닌 IEnumerable[<T>] 대해 언급 했으므로 카운트 등에 의존 할 수는 없습니다. 그래서 foreach 를 풀어 보려합니다.

using(var iter = source.GetEnumerator()) {
    if(iter.MoveNext()) {
        T last = iter.Current;
        while(iter.MoveNext()) {
            // here, "last" is a non-final value; do something with "last"
            last = iter.Current;
        }
        // here, "last" is the FINAL one; do something else with "last"
    }
}

위의 내용은 기술적 으로 IEnuemerable<T> 에만 유효합니다. 비 제너릭의 경우 다음이 필요합니다.

var iter = source.GetEnumerator();
using(iter as IDisposable) {
    if(iter.MoveNext()) {
        SomeType last = (SomeType) iter.Current;
        while(iter.MoveNext()) {
            // here, "last" is a non-final value; do something with "last"
            last = (SomeType) iter.Current;
        }
        // here, "last" is the FINAL one; do something else with "last"
    }
}




control-flow