2

我有这个方法:

public override void respond(params string[] resargs)
{
    foreach (command cmd in pndgcmds)
    {
        cmd(this);
    }

    if (objs[resargs[0]].status)
        objs[resargs[0]].request(resargs);
    else
    {
        pndgcmds.Add(
            (myclass master) =>
            {
                if (master.objs[resargs[0]].status != true) return;
                master.objs[resargs[0]].request(resargs);
                //code to remove the delegate
            });
    }
}

它检查对象是否能够响应,如果能够响应,则使其响应,否则将命令存储在字典中,以便在下次调用响应时检查并调用状态。

我有两个问题。

  1. 如何编写代码来删除委托?我不知道该怎么做。

  2. 如您所见,委托的大部分内部工作依赖于方法参数。代表将如何表现?

提前致谢!

4

1 回答 1

6

匿名方法很难删除,因为 captire-context 的实例仅在创建时可用,因此是必需的。幸运的是,有一个技巧:

SomeDelegateType handler = null;
handler = (myclass master) =>
            {
                if (master.objs[resargs[0]].status != true) return;
                master.objs[resargs[0]].request(resargs);
                pndgcmds.Remove(handler);
            };
pndgcmds.Add(handler);

这现在是一个自退订处理程序,它会在调用时自行退订。请注意,要做到这一点,我们需要存储委托实例 ( handler),但我们随后会在该变量上创建一个闭包。初始=null是明确分配的要求。

您应该注意该resargs变量也被捕获,如果索引零处的值在订阅之后但在调用之前发生更改,这可能会导致混淆。如果您想使用值“now”,则将其关闭:

SomeDelegateType handler = null;
string val = resargs[0];
handler = (myclass master) =>
            {
                if (master.objs[val].status != true) return;
                master.objs[val].request(resargs);
                pndgcmds.Remove(handler);
            };
pndgcmds.Add(handler);
于 2012-09-02T11:41:41.680 回答