Csharp/C#教程:C#代表,参考解析时间分享


C#代表,参考解析时间

我有一个关于.net委托的简单问题。 说我有这样的事情:

public void Invoke(Action action) { Invoke(() => action(this.Value)); } public void Invoke(Action action) { m_TaskQueue.Enqueue(action); } 

第一个函数包含对this.Value的引用。 在运行时,当第一个带有generics参数的方法被调用时,它会以某种方式提供this.Value到第二个,但是如何? 我想到了这些:

我认为这将是名称样式的调用,但无法找到任何文档,所以想知道它是否是一个明确定义的行为。 这个类类似于Scala或Erlang中的Actor,所以我需要它是线程安全的。 我不希望Invoke函数立即取消引用Value ,这将通过m_TaskQueuethis对象的安全线程中m_TaskQueue

让我通过描述我们为此实际生成的代码来回答您的问题。 我将重命名你混淆的其他Invoke方法; 没有必要了解这里发生了什么。

假设你说

 class C { public T Value; public void Invoke(Action action) { Frob(() => action(this.Value)); } public void Frob(Action action) { // whatever } } 

编译器生成的代码就像您实际编写的一样:

 class C { public T Value; private class CLOSURE { public Action ACTION; public C THIS; public void METHOD() { this.ACTION(this.THIS.Value); } } public void Invoke(Action action) { CLOSURE closure = new CLOSURE(); closure.THIS = this; closure.ACTION = action; Frob(new Action(closure.METHOD)); } public void Frob(Action action) { // whatever } } 

这是否回答你的问题?

委托存储对变量的引用,而不是它的值。 如果你想保持当前值(假设它是一个值类型),你需要制作它的本地副本:

 public void Invoke(Action action) { var localValue = this.Value; Invoke(() => action(localValue)); } 

如果它是可变引用类型,则可以创建本地克隆/深层副本。

真正的关键是要记住范围是词汇; 这是编译器负责的事情。 所以它捕获变量 ,而不是它们的 。 这些值是值类型还是引用类型是另一回事。

也许更改代表行为的一个稍微更极端的例子将有助于:

 var myVariable = "something"; Action a = () => Console.WriteLine(myVariable); myVariable = "something else entirely" a(); 

打印“完全不同的东西”。 从这个角度来看,包装,保存或移动function的次数并不重要; 它仍然指的是它所包含的变量。 因此,简而言之,重要的是当委托实际执行时封闭变量的值。

上述就是C#学习教程:C#代表,参考解析时间分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/984672.html

(0)
上一篇 2021年12月20日
下一篇 2021年12月20日

精彩推荐