gpt4 book ai didi

.net - 为什么在using语句内的闭包内捕获可变结构变量会改变其局部行为?

转载 作者:行者123 更新时间:2023-12-03 12:16:23 26 4
gpt4 key购买 nike

更新:好吧,现在我已经去做了:我对此做了filed a bug report with Microsoft,因为我严重怀疑这是正确的行为。也就是说,我仍然不确定100%对this question的看法;所以我可以看到“正确”的东西在某种程度上是开放的。

我的感觉是,要么Microsoft会接受这是一个错误,要么响应是对using语句中的可变值类型变量的修改构成了未定义的行为。

另外,对于它的值(value),我至少对这里发生的事情有一个猜测。我怀疑编译器正在为闭包生成一个类,将局部变量“提升”到该类的实例字段。并且由于它在using块之内,所以使其成为readonly 字段。正如LukeH在a comment to the other question中指出的那样,这将防止MoveNext之类的方法调用修改字段本身(它们会影响副本)。

注意:为了简化可读性,我已经缩短了这个问题,尽管它仍然不够简短。有关完整的原始(较长)问题,请参阅编辑历史记录。

我已经阅读了我认为是ECMA-334的相关部分的内容,并且似乎无法找到这个问题的最终答案。我将首先陈述问题,然后为感兴趣的人提供指向一些其他评论的链接。



如果我具有实现IDisposable的可变值类型,则可以(1)调用一个方法,该方法在using语句中修改局部变量的值状态,并且代码的行为符合我的预期。但是,一旦我在using语句内的闭包内捕获了有问题的变量,(2)对该值的修改在本地范围内就不再可见。

仅当变量在using语句内的闭包内捕获时,这种行为才很明显。当仅存在一个(using)或另一个条件(关闭)时,这并不明显。

为什么在using语句的闭包内捕获可变值类型的变量会改变其本地行为?

下面是说明第1项和第2项的代码示例。这两个示例都将利用以下演示Mutable值类型:

struct Mutable : IDisposable
{
int _value;
public int Increment()
{
return _value++;
}

public void Dispose() { }
}

1.更改 using块中的值类型变量
using (var x = new Mutable())
{
Console.WriteLine(x.Increment());
Console.WriteLine(x.Increment());
}

输出代码输出:
01

2. Capturing a value type variable inside a closure within a using block

using (var x = new Mutable())
{
// x is captured inside a closure.
Func<int> closure = () => x.Increment();

// Now the Increment method does not appear to affect the value
// of local variable x.
Console.WriteLine(x.Increment());
Console.WriteLine(x.Increment());
}

上面的代码输出:

0
0

进一步的评论

已经注意到,Mono编译器提供了我期望的行为(在 using +闭包的情况下,仍然可以看到对局部变量值的更改)。我不清楚这种行为是否正确。

有关此问题的更多想法,请参阅 here

最佳答案

这是一个已知的错误;我们是几年前发现的。该修复程序可能会被破坏,并且问题非常模糊。这些是修复它的要点。因此,它从来没有被重视过高以至于无法实际修复它。

几年来,这一直在我潜在的博客主题中。也许我应该写出来。

顺便说一下,您对解释该错误的机制的猜想是完全准确的;不错的通灵调试。

所以,是的,已知的错误,但是无论如何,感谢您的报告!

关于.net - 为什么在using语句内的闭包内捕获可变结构变量会改变其局部行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4642665/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com