foreach 루프는 C #에서 어떻게 작동합니까? [닫은]


86

foreach루프 를 사용할 수있는 클래스 유형은 무엇입니까?


5
선택한 답변이 실제로 정답을 대표하지 않기 때문에 다른 수락 된 답변을 선택하는 것이 좋습니다.
George Stocker

답변:


162

실제로 엄밀히 말하면 메서드와 속성으로 무언가를 반환 foreach하는 공용 GetEnumerator()메서드 만 사용해야합니다 . 그러나 가장 일반적인 이것의 의미는 구현이 뭔가 "입니다 / , 반환 /을 .bool MoveNext()? Current {get;}IEnumerableIEnumerable<T>IEnumeratorIEnumerator<T>

암시으로이 구현하는 것을 포함 ICollection/ ICollection<T>등 같은 아무것도 Collection<T>, List<T>, 배열 ( T[]) 등의 표준 "데이터 수집"그래서 일반적으로 지원됩니다 foreach.

첫 번째 요점을 증명하기 위해 다음이 잘 작동합니다.

using System;
class Foo {
    public int Current { get; private set; }
    private int step;
    public bool MoveNext() {
        if (step >= 5) return false;
        Current = step++;
        return true;
    }
}
class Bar {
    public Foo GetEnumerator() { return new Foo(); }
}
static class Program {
    static void Main() {
        Bar bar = new Bar();
        foreach (int item in bar) {
            Console.WriteLine(item);
        }
    }
}

어떻게 작동합니까?

foreach(int i in obj) {...}좀 같은 foreach 루프는 다음과 같습니다.

var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
    int i; // C# 5.0
    i = tmp.Current;
    {...} // your code
}

그러나 변형이 있습니다. 예를 들어 열거 자 (tmp)가를 지원하는 경우이 IDisposable역시 사용됩니다 (와 유사 using).

차분 참고 선언 "의 위치에서 int i" 내부 (C # 5.0) 대에서 외부 루프 (C # 4.0 업). i코드 블록 내에서 익명 메서드 / 람다 를 사용 하는 경우 중요합니다 . 그러나 그것은 또 다른 이야기입니다 ;-p


3
깊이 들어가면 +1. 나는 일반적으로 '초보자'질문 일 수있는 질문에 대해서는 깊이 들어 가지 않습니다. 새로운 프로그래머에게는 압도적으로 보일 수 있기 때문입니다.
George Stocker

사실, Gortok-그래서 나는 목록 / 배열 / 등에 관한 것들을 추적했습니다.
Marc Gravell

루프 변수에 대한 암시 적 런타임 캐스팅을 언급하는 것이 좋습니다. 유형 비 호환성 예외를 생성 할 수 있습니다.
Daniel Earwicker

3
잊지 마세요 : foreach와 함께 배열을 사용할 때 컴파일러는 간단한 파일을 생성합니다 for-loop(IL로 작업 할 때 이것을 볼 수 있습니다).
Felix K.

1
@Marc Gravell : 좋아, 멋지다! 나는 적어도 나에게는 더 명확하게 게시물을 편집했다. 결국 배치는 C # 5.0에서 중요 할뿐만 아니라 항상 중요합니다. 괜찮 으시길 바랍니다.
Paul Groke

7

에서 MSDN :

foreach은 배열 또는 개체 컬렉션의 각 요소에 대해 포함 된 문 그룹을 반복합니다 . 이 foreach문은 원하는 정보를 얻기 위해 컬렉션을 반복하는 데 사용되지만 예측할 수없는 부작용을 방지하기 위해 컬렉션의 내용을 변경하는 데 사용해서는 안됩니다. (강조 광산)

따라서 배열이있는 경우 다음과 같이 foreach 문을 사용하여 배열을 반복 할 수 있습니다.

 int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
    foreach (int i in fibarray)
    {
        System.Console.WriteLine(i);
    }

다음 List<T>과 같이 컬렉션 을 반복하는 데 사용할 수도 있습니다 .

List<string> list = new List<string>();

foreach (string item in list)
{
    Console.WriteLine(item);
}

4
이상하게도 MSDN ( msdn.microsoft.com/en-us/library/9yb8xew9(VS.80).aspx )에 따르면 개체 유형은 IEnumerable을 구현할 필요가 없습니다. GetEnumerator, MoveNext, Reset 및 Current를 올바른 방식으로 정의하는 모든 유형이 작동합니다. 이상 하죠?
Sean Reilly

산뜻한. 나는 그것을 몰랐다. :-)
George Stocker


2

문서는 다음과 같습니다. 컬렉션 개체가 있는 배열을 사용한 본문

"컬렉션 요소의 유형은 식별자 유형으로 변환 가능해야합니다"라는 점에 유의해야합니다. 이것은 때때로 컴파일 타임에 확인할 수 없으며 인스턴스 유형이 참조 유형에 할당되지 않는 경우 런타임 예외를 생성 할 수 있습니다.

오렌지와 같은 과일 바구니에 Apple이 아닌 경우 런타임 예외가 생성됩니다.

List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)

이렇게하면 Enumerable.OfType을 사용하여 목록을 Apple로만 안전하게 필터링합니다.

foreach(Apple a in fruitBasket.OfType<Apple>() )

-1
IList<ListItem> illi = new List<ListItem>();
ListItem li = null;

foreach (HroCategory value in listddlsubcategory)
{
    listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id);
    li = new ListItem();
    li.Text = value.Description;
    li.Value = value.Id.ToString();
    illi.Add(li);
    IList<ListItem> newilli = new List<ListItem>();
    newilli = SubCatagoryFunction(listddlsubcategoryext, "-->");
    foreach (ListItem c in newilli)
    {
        illi.Add(c);
    }
}

-1

이 주제에 대한 유용한 정보는 MSDN 에서도 찾을 수 있습니다 . 그 기사에서 본질을 취하십시오 :

foreach 키워드는 컬렉션을 열거하고 컬렉션의 각 요소에 대해 한 번씩 포함 된 문을 실행합니다.

foreach (var item in collection)
{
    Console.WriteLine(item.ToString());
}

컴파일러는 위의 예제에 표시된 foreach 루프를 다음 구문과 유사한 것으로 변환합니다.

IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
    var item = enumerator.Current;
    Console.WriteLine(item.ToString());
}

-2

당신은 이것을 시도 할 수 있습니다 ...

List<int> numbers = new List<int>();
        numbers.Add(5);
        numbers.Add(15);
        numbers.Add(25);
        numbers.Add(35);

        Console.WriteLine("You are added total number: {0}",numbers.Count);
        foreach (int number in numbers)
        {
            Console.WriteLine("Your adding Number are: {0}", number);
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.