C# 如何在不迭代到最后的情况下放弃IEnumerator?
考虑下面的代码,第一个代码演示了在完成对字符串的IEnumerable的迭代时执行“清理”。第二关是让我伤心的事。我需要能够在结束之前放弃IEnumerable,然后执行清理代码。但是如果你运行这个程序,你会发现在第二个关卡中,清理永远不会开火 放弃这样一个IEnumerable的首选方式是什么C# 如何在不迭代到最后的情况下放弃IEnumerator?,c#,C#,考虑下面的代码,第一个代码演示了在完成对字符串的IEnumerable的迭代时执行“清理”。第二关是让我伤心的事。我需要能够在结束之前放弃IEnumerable,然后执行清理代码。但是如果你运行这个程序,你会发现在第二个关卡中,清理永远不会开火 放弃这样一个IEnumerable的首选方式是什么 static void Main(string[] args) { // first pass foreach (String color in readColors())
static void Main(string[] args)
{
// first pass
foreach (String color in readColors())
Console.WriteLine(color);
// second pass
IEnumerator<string> reader = readColors().GetEnumerator();
if (reader.MoveNext())
{
Console.WriteLine(reader.Current);
reader.Dispose();
}
}
static IEnumerable<string> readColors()
{
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++)
yield return colors[i];
Console.WriteLine("Cleanup goes here");
}
static void Main(字符串[]args)
{
//第一关
foreach(readColors()中的字符串颜色)
控制台。WriteLine(彩色);
//第二关
IEnumerator reader=readColors().GetEnumerator();
if(reader.MoveNext())
{
Console.WriteLine(reader.Current);
reader.Dispose();
}
}
静态IEnumerable readColors()
{
字符串[]颜色={“红色”、“绿色”、“蓝色”};
for(int i=0;i
这是放弃它的一种方式。你没有看到的原因
Cleanup goes here
控制台上打印的原因是(int i=0;iIDisposable
对象的首选模式。这是首选,因为即使发生异常,也会导致调用IEnumerator.Dispose
using (IEnumerator<string> reader = readColors().GetEnumerator()) {
reader.MoveNext();
Console.WriteLine(reader.Current);
}
使用(IEnumerator reader=readColors().GetEnumerator()){
reader.MoveNext();
Console.WriteLine(reader.Current);
}
至于强制执行您必须执行的清理代码,您可以执行以下操作:
static IEnumerable<string> readColors() {
string[] colors = { "red", "green", "blue" };
try {
for (int i = 0; i < colors.Length; i++) {
yield return colors[i];
}
}
finally {
Console.WriteLine("Cleanup goes here");
}
}
static IEnumerable readColors(){
字符串[]颜色={“红色”、“绿色”、“蓝色”};
试一试{
for(int i=0;i
您需要将迭代器方法的主要部分放到try中。最后,在finally中使用清理代码:
public IEnumerable<string> readColors()
{
try
{
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++)
yield return colors[i];
}
finally
{
Console.WriteLine("Cleanup goes here");
}
}
public IEnumerable readColors()
{
尝试
{
字符串[]颜色={“红色”、“绿色”、“蓝色”};
for(int i=0;i
请记住,在后台,迭代器方法会导致创建一个单独的类,该类实现IEnumerable
和IEnumerator
。通过将清理放在finally块中,它将在生成的类“Dispose
方法中结束
[编辑:(正如其他答案中指出的那样)与手动调用
Dispose
的方法相比,更喜欢使用语句。我以为你这样做只是为了突出讨论中的问题,但无论如何都值得指出]我认为进行清理的首选方法是使用IDisposable
。在这种情况下,您最好使用特定的IEnumerable
实现自己的IEnumerable
,并使用正常的Dispose
方法。使用foreach
可免费获得dispose
class MyEnumerator : IEnumerator<string>
{
// ...
#region IDisposable Members
public void Dispose()
{
// do your cleanup here
throw new NotImplementedException();
}
#endregion
// ...
}
类分子:IEnumerator
{
// ...
#区域IDisposable成员
公共空间处置()
{
//你在这里打扫吗
抛出新的NotImplementedException();
}
#端区
// ...
}
试试看{
字符串[]颜色={“红色”、“绿色”、“蓝色”};
for(int i=0;i
我可能遗漏了一些内容,或者您的示例过于简化……但是您希望在readColors中的枚举结束时运行什么清理?看起来GC应该能够自己处理事情。如果你有一个自定义集合,你也可以实现IDisposable?!。你不需要实现你自己的——只要你把清理放在finally块中,编译器就会帮你完成。你的答案可能是正确的,对于简单的情况,我认为你的答案更好。不是我否决了你——我只是指出你不需要实现你自己的。我认为投反对票会有点苛刻——你的答案没有错——在某些情况下,只有其他方式更可取。当我投反对票时,只有几行答案似乎没有多大意义。现在你已经澄清了,我已经把它删除了。@Rob Levine:我过早地点击了提交,这样就足够公平了。谢谢你回来评论。这是正确的答案,一旦你这么做了,你可以简化你的第二行代码,仍然使用“foreach”,而不是你现在拥有的更复杂的代码。只需执行以下操作:foreach(readColors()中的字符串颜色){Console.WriteLine(颜色);break;}
try {
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++) {
if(condition == true)
break;
yield return colors[i];
}
}
finally {
Console.WriteLine("Cleanup goes here");
}