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_TaskQueue
在this
对象的安全线程中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