为什么我的IEnumerable UserControl在用foreach枚举后被丢弃
本文关键字:枚举 foreach 我的 IEnumerable UserControl 在用 为什么 | 更新日期: 2023-09-27 17:59:57
我有一个带有内部列表的用户控件,我通过实现IEnumerable公开了该列表。当我使用foreach对其进行枚举时,用户控件会被丢弃。为什么会发生这种情况?
要复制的示例:
using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
public class VanishingControl : UserControl, IEnumerable, IEnumerator
{
string[] strings = { "uno", "due", "tres" };
int position = -1;
public IEnumerator GetEnumerator()
{
return this;
}
public object Current
{
get { return strings[position]; }
}
public bool MoveNext()
{
position++;
return position < strings.Length;
}
public void Reset()
{
position = 0;
}
protected override void Dispose(bool disposing)
{
Console.WriteLine("bye!");
base.Dispose(disposing);
}
}
public class Vanish : Form
{
private VanishingControl vc = new VanishingControl();
public Vanish()
{
vc.BackColor = Color.Black;
vc.Click += vc_Click;
Controls.Add(vc);
}
void vc_Click(object sender, EventArgs e)
{
foreach (string s in vc)
Console.WriteLine(s);
}
[STAThread]
static void Main()
{
Application.Run(new Vanish());
}
}
在调试器中运行它,然后单击黑色方块。
IEnumerator
实现的接口之一是IDisposable
。一旦处理完项目,foreach
循环将在循环源上调用Dispose
。
一个更好的解决方案是将UserControl
分解为两部分
UserControl
减去可枚举接口- 公开其包含的集合的属性/方法
例如
public class VanishingControl : UserControl
{
string[] strings = { "uno", "due", "tres" };
public IEnumerable<string> GetItems() {
foreach (var current in strings) {
yield return current;
}
}
}
因为控件是它自己的枚举器:-)
枚举器在foreach
之后自动释放。
我建议将枚举器制作成一个单独的类。或者,只使用标准集合作为成员,而不使控件本身成为IEnumerable
。
这是原因:
public IEnumerator GetEnumerator()
{
return this;
}
IEnumerator
接口之一是IDisposable
,foreach循环在工作结束时调用Dispose
方法。
每次调用GetEnumerator方法时,都应该提供新的IEnumerator,并避免在一个实现中同时使用这两个接口。这是由LINQ完成的,但这是特定的情况。
应该有一个实现IEnumerator
的子类,而不是类VanishingControl
中的IEnumerator
,并且在GetEnumeratorn中返回该类的新实例。