有人可以分享一个将foreach
关键字与自定义对象一起使用的简单示例吗?
3 回答
鉴于标签,我假设您的意思是 .NET - 我将选择谈论 C#,因为这就是我所知道的。
该foreach
语句(通常)使用IEnumerable
andIEnumerator
或它们的通用表亲。表格声明:
foreach (Foo element in source)
{
// Body
}
其中source
implementsIEnumerable<Foo>
大致相当于:
using (IEnumerator<Foo> iterator = source.GetEnumerator())
{
Foo element;
while (iterator.MoveNext())
{
element = iterator.Current;
// Body
}
}
请注意,IEnumerator<Foo>
在末尾设置了,但是该语句退出了。这对于迭代器块很重要。
要自己实现IEnumerable<T>
,IEnumerator<T>
最简单的方法是使用迭代器块。与其在这里写下所有的细节,不如直接参考C# in Depth 的第 6 章,这是免费下载的。第 6 章的全部内容都是关于迭代器的。我的 C# in Depth 站点上还有几篇文章:
作为一个简单的例子:
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
}
要实现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
}
}
(我在这里假设 C#)
如果您有一个自定义对象列表,您可以像使用任何其他对象一样使用 foreach:
List<MyObject> myObjects = // something
foreach(MyObject myObject in myObjects)
{
// Do something nifty here
}
如果您想创建自己的容器,您可以使用 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();
}
}
然后将它与 foreach 一起使用:
MyContainer myContainer = new MyContainer(10);
foreach(int i in myContainer)
Console.WriteLine(i);
来自MSDN 参考:
foreach 语句不限于IEnumerable
类型,可以应用于满足以下条件的任何类型的实例:
具有GetEnumerator
返回类型为类、结构或接口类型的公共无参数方法,该方法的返回类型GetEnumerator
具有公共 Current 属性和MoveNext
返回类型为布尔值的公共无参数方法。
如果您声明这些方法,则可以使用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)
{
}