foreach循环如何在C#中工作?[关闭]


86

哪些类型的类可以使用foreach循环?


5
您可能想要选择其他可接受的答案,因为您选择的答案并不能真正代表正确的答案。
George Stocker

Answers:


162

实际上,严格来说,您需要使用的foreach只是一个公共GetEnumerator()方法,该bool MoveNext()方法返回带有方法和? Current {get;}属性的内容。但是,最常见的含义是“实现IEnumerable/的操作IEnumerable<T>,返回IEnumerator/ IEnumerator<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) {...}kinda之类的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在代码块内使用匿名方法/ lambda,则非常重要。但这是另一个故事;-p


3
+1为深入。我通常不会深入探讨可能是“初学者”的问题,因为这对于新程序员来说似乎不胜枚举。
George Stocker

是的,Gortok-所以我跟进了有关列表/数组/等的内容。
Marc Gravell

最好提及将隐式运行时强制转换为循环变量-可能产生类型不兼容异常。
Daniel Earwicker,2009年

3
别忘了:当将数组与foreach一起使用时,编译器会创建一个简单的数组for-loop(使用IL时可以看到这一点)。
Felix K. 2012年

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/zh-cn/library/9yb8xew9 ( VS.80 ) .aspx),对象类型不需要实现IEnumerable。任何以正确方式定义GetEnumerator,MoveNext,Reset和Current的类型都可以使用。奇怪吧?
肖恩·赖利

整齐。我不知道 :-)
George Stocker


2

这是文档: 主文章 带数组的 集合对象

重要的是要注意“集合元素的类型必须可以转换为标识符类型”。如果实例类型不能分配给引用类型,则有时无法在编译时进行检查,并且会生成运行时异常。

如果水果篮中有非Apple(例如橙色),则会生成运行时异常。

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

这样可以安全地将列表筛选为仅使用Enumerable.OfType的苹果。

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);
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.