繁体   English   中英

为什么 using 语句在 IEnumerator 上起作用,它有什么作用?

[英]Why does the using statement work on IEnumerator and what does it do?

回到当我学习foreach ,我在某处读到:

foreach (var element in enumerable)
{
    // do something with element
}

基本上相当于:

using (var enumerator = enumerable.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        var element = enumerator.Current;

        // do something with element
    }
}

如果IEnumeratorIEnumerator<T>都没有实现IDisposable为什么这段代码甚至可以编译? C# 语言规范似乎只在IDisposable的上下文中提到using语句。

这样的using语句有什么作用?

请查看以下有关foreach语句的链接 如果可能,它使用带有 Dispose 调用的 try/finally 块。 这就是using语句背后的代码。

IEnumerator可能不实现IDisposableGetEnumerator()返回一个IEnumerator<T> 来自IEnumerator<T>上的文档:

此外,IEnumerator 实现了 IDisposable,这需要您实现 Dispose 方法。 这使您可以在使用其他资源时关闭数据库连接或释放文件句柄或类似操作。 如果没有要处理的额外资源,请提供一个空的 Dispose 实现。

这当然是假设您的枚举是IEnumerable<T>而不仅仅是IEnumerable 如果您的原始枚举只是一个IEnumerable那么它将无法编译。

似乎还没有人回答主要问题:

这样的 using 语句有什么作用?

我将使用我最喜欢的一本书中的一个例子 - Jon Skeet 的C# in Depth 您可能会得到由这样的函数生成的IEnumerator<T>的结果:

static IEnumerable<string> Iterator()
{
    try
    {
        Console.WriteLine("Before first yield");
        yield return "first";
        Console.WriteLine("Between yields");
        yield return "second";
        Console.WriteLine("After second yield");
    }
    finally
    {
        Console.WriteLine("In finally block");
    }
}

然后你会像这样使用它:

foreach (string value in Iterator())
{
    Console.WriteLine("Received value: {0}", value);
    if (value != null)
    {
        break;
    }
}

当我们在第一次迭代时中断,迭代器只返回序列中的第一个"first"值。 现在你的迭代器如何“知道”你不会继续到循环结束,所以它会触发它的finally块? 这里是隐藏的using语句。 如果您不能使用foreach循环,那么上面示例中的代码将如下所示:

IEnumerable<string> enumerable = Iterator();
using (IEnumerator<string> enumerator = enumerable.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        string value = enumerator.Current;
        Console.WriteLine("Received value: {0}", value);
        if (value != null)
        {
            break;
        }
    }
}

当我们离开隐藏using语句的范围时, Dispose()方法会触发:

finally
{
    Console.WriteLine("In finally block");
}

*以上所有代码行和部分文本均由 Jon Skeet 提供。 我本可以重写它,但决定我宁愿让它保持原样。 如果作者不想让我分享它 - 我会尽快删除答案或重写它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM