Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不迭代到最后的情况下放弃IEnumerator?_C# - Fatal编程技术网

C# 如何在不迭代到最后的情况下放弃IEnumerator?

C# 如何在不迭代到最后的情况下放弃IEnumerator?,c#,C#,考虑下面的代码,第一个代码演示了在完成对字符串的IEnumerable的迭代时执行“清理”。第二关是让我伤心的事。我需要能够在结束之前放弃IEnumerable,然后执行清理代码。但是如果你运行这个程序,你会发现在第二个关卡中,清理永远不会开火 放弃这样一个IEnumerable的首选方式是什么 static void Main(string[] args) { // first pass foreach (String color in readColors())

考虑下面的代码,第一个代码演示了在完成对字符串的IEnumerable的迭代时执行“清理”。第二关是让我伤心的事。我需要能够在结束之前放弃IEnumerable,然后执行清理代码。但是如果你运行这个程序,你会发现在第二个关卡中,清理永远不会开火

放弃这样一个IEnumerable的首选方式是什么

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;i的循环从未运行到完成。有关如何强制执行清除代码,请参见下文

还有一种方法。这是在C#中使用
IDisposable
对象的首选模式。这是首选,因为即使发生异常,也会导致调用
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");
}