【问题标题】:Invoke Action created from Expression<Action> in another scope在另一个范围内调用从 Expression<Action> 创建的动作
【发布时间】:2012-11-06 14:54:40
【问题描述】:

考虑以下简单示例:

private Action _action;

public Form1() { InitializeComponent(); }

private void button1_Click(object sender, EventArgs e)
{
    string msg = "test";
    Expression<Action> exp = () => MessageBox.Show(msg);
    _action = exp.Compile();
    msg = "testC";
}

private void button2_Click(object sender, EventArgs e)
{
    _action();
}

当 button2 被点击时,我看到testC

我的问题是:

我想存储稍后运行的操作。我可以安全地存储compile() 创建的委托并随时使用它吗?

我的问题主要是关于方法参数。我不知道它们是如何存储的(通过引用或值),是否可以同时被 GC 清除。总的来说,我怀疑这是正确的方法。另外,msdn 也没有多大帮助。

我正在创建一个支持要执行的高优先级操作的 JobManager。有一堆默认操作和一些需要添加的高优先级。这部分是我注册高优先级作业的地方(使用 lambda -> 获取方法 -> 创建委托 -> 存储它 -> 在需要时运行)。我不确定这是否是存储动作的正确方法。

【问题讨论】:

  • 你为什么要创建一个表达式并编译它而不是首先从 lambda 创建一个动作?
  • @Servy 如上所述I doubt that this is the correct approach。谢谢你的提示。我被引导到这种方法,并且对参数的使用感到困惑。
  • 您只需使用_action = () =&gt; MessageBox.Show(msg);。至于它是存储引用还是值,只要执行代码(你做了)就给你答案了,不是吗?
  • 我需要更多理论知识。我可以看到它的工作原理!

标签: c# .net-3.5 delegates lambda


【解决方案1】:

是的,你可以。
lambda 表达式创建了一个 闭包,它保存了对其从外部函数使用的局部变量的引用。

这个闭包在代理的Target 属性中被引用。
只要您持有对委托的引用,这些变量就不会被 GC。

如需更详细地了解其工作原理,请参阅my blog post

【讨论】:

    猜你喜欢
    • 2015-06-28
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多