如何在 C# 中的自定义对象上使用 foreach 关键字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/348964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:04:37  来源:igfitidea点击:

How to use foreach keyword on custom Objects in C#

c#foreach

提问by user42070

Can someone share a simple example of using the foreachkeyword with custom objects?

有人可以分享一个将foreach关键字用于自定义对象的简单示例吗?

采纳答案by Jon Skeet

Given the tags, I assume you mean in .NET - and I'll choose to talk about C#, as that's what I know about.

鉴于标签,我假设您的意思是在 .NET 中 - 我将选择谈论 C#,因为这就是我所知道的。

The foreachstatement (usually) uses IEnumerableand IEnumeratoror their generic cousins. A statement of the form:

foreach语句(通常)使用IEnumerable和/IEnumerator或它们的通用表亲。声明形式:

foreach (Foo element in source)
{
    // Body
}

where sourceimplements IEnumerable<Foo>is roughlyequivalent to:

其中source器具IEnumerable<Foo>大致等效于:

using (IEnumerator<Foo> iterator = source.GetEnumerator())
{
    Foo element;
    while (iterator.MoveNext())
    {
        element = iterator.Current;
        // Body
    }
}

Note that the IEnumerator<Foo>is disposed at the end, however the statement exits. This is important for iterator blocks.

请注意,IEnumerator<Foo>被处理在最后,但是语句退出。这对于迭代器块很重要。

To implement IEnumerable<T>or IEnumerator<T>yourself, the easiest way is to use an iterator block. Rather than write all the details here, it's probably best to just refer you to chapter 6 of C# in Depth, which is a free download. The whole of chapter 6 is on iterators. I have another couple of articles on my C# in Depth site, too:

要实现IEnumerable<T>IEnumerator<T>自己实现,最简单的方法是使用迭代器块。与其在此处写下所有详细信息,不如仅将您介绍给C# in Depth 的第 6 章,该章可免费下载。整个第 6 章都是关于迭代器的。我的 C# in Depth 网站上还有另外几篇文章:

As a quick example though:

举个简单的例子:

public IEnumerable<int> EvenNumbers0To10()
{
    for (int i=0; i <= 10; i += 2)
    {
        yield return i;
    }
}

// Later
foreach (int x in EvenNumbers0To10())
{
    Console.WriteLine(x); // 0, 2, 4, 6, 8, 10
}

To implement IEnumerable<T>for a type, you can do something like:

要实现IEnumerable<T>一个类型,您可以执行以下操作:

public class Foo : IEnumerable<string>
{
    public IEnumerator<string> GetEnumerator()
    {
        yield return "x";
        yield return "y";
    }

    // Explicit interface implementation for nongeneric interface
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator(); // Just return the generic version
    }
}

回答by Mats Fredriksson

(I assume C# here)

(我假设 C# 在这里)

If you have a list of custom objects you can just use the foreach in the same way as you do with any other object:

如果您有一个自定义对象列表,您可以像使用任何其他对象一样使用 foreach:

List<MyObject> myObjects = // something
foreach(MyObject myObject in myObjects)
{
     // Do something nifty here
}

If you want to create your own container you can use the yield keyword (from .Net 2.0 and upwards I believe) together with the IEnumerable interface.

如果您想创建自己的容器,您可以将 yield 关键字(我相信从 .Net 2.0 及更高版本)与 IEnumerable 接口一起使用。

class MyContainer : IEnumerable<int>
{
    private int max = 0;
    public MyContainer(int max)
    {
        this.max = max;
    }

    public IEnumerator<int> GetEnumerator()
    {
        for(int i = 0; i < max; ++i)
            yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

And then use it with foreach:

然后将它与 foreach 一起使用:

MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
    Console.WriteLine(i);

回答by Brackets

From MSDN Reference:

MSDN 参考

The foreach statement is not limited to IEnumerabletypes and can be applied to an instance of any type that satisfies the following conditions:

foreach 语句不限于IEnumerable类型,可以应用于满足以下条件的任何类型的实例:

has the public parameterless GetEnumeratormethod whose return type is either class, struct, or interface type, the return type of the GetEnumeratormethod has the public Current property and the public parameterless MoveNextmethod whose return type is Boolean.

具有GetEnumerator返回类型为类、结构或接口类型GetEnumerator的公共无参数MoveNext方法,该方法的返回类型具有公共 Current 属性和公共无参数方法,其返回类型为布尔值。

If you declare those methods, you can use foreachkeyword without IEnumerableoverhead. To verify this, take this code snipped and see that it produces no compile-time error:

如果声明这些方法,则可以使用foreach关键字而无需IEnumerable开销。要验证这一点,请截断此代码并查看它是否不会产生编译时错误:

class Item
{
    public Item Current { get; set; }
    public bool MoveNext()
    {
        return false;
    }
}

class Foreachable
{
    Item[] items;
    int index;
    public Item GetEnumerator()
    {
        return items[index];
    }
}

Foreachable foreachable = new Foreachable();
foreach (Item item in foreachable)
{

}