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

问题描述 投票:0回答:3

当我学习

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
    }
}

如果

IEnumerator
IEnumerator<T>
都没有实现
IDisposable
,为什么这段代码还能编译? C# 语言规范似乎只在
using
的上下文中提到了
IDisposable
语句。

这样的

using
声明有什么作用?

c# language-lawyer
3个回答
4
投票

请检查以下关于 foreach 语句的链接已存档)。如果可能的话,它使用带有 Dispose 调用的 try/finally 块。这就是 using 语句后面的代码。


2
投票

IEnumerator
可能不会实现
IDisposable
GetEnumerator()
返回一个
IEnumerator<T>
,它可以实现。来自
IEnumerator<T>
上的文档:

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

这当然是假设您的枚举是一个

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


1
投票

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

这样的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 提供。我本来可以重写它,但我决定还是原封不动地保留它。如果作者不想让我分享 - 我会尽快删除答案或重写它。
    

© www.soinside.com 2019 - 2024. All rights reserved.