【问题标题】:Subscribe to a delegate that was passed as method argument订阅作为方法参数传递的委托
【发布时间】:2016-02-06 21:45:02
【问题描述】:

我正在尝试将循环编程模式构建到通用类中以供代码重用。此模式的一部分在异步操作期间根据需要线程安全地订阅/取消订阅委托(多播委托用作事件)。

以下代码无法编译。我面临的问题是 C# 允许我将委托作为方法参数传递,但是在 MyWorker 类中的任何地方,订阅 +=,-= 操作都会导致错误。 (在外部的同一个代表上工作正常)。

[Operator '+=' cannot be applied to operands of type 'delegateT' and 'method group']

语法错误? 委托范围限制? 这是语言不允许的吗?

public class MyWorker<delegateT,argT>
{
    private delegateT mDelegate;

    public MyWorker(delegateT d)
    {
        mDelegate = d; //save delegate (reference?) for use later
    }

    public void DoWorkAsync()
    {
        mDelegate += m_subscriber; //ERROR: Operator '+=' cannot be applied to operands of type 'delegateT'...

        //...Do some work that causes delegate to fire...

        mDelegate -= m_subscriber; //ERROR: Operator '-=' cannot be applied to operands of type 'delegateT'...
    }

    private void m_subscriber(argT arg)
    {
        Console.WriteLine("Received: " + arg.ToString());
    }
}

请注意,泛型似乎不是原因;我尝试使用静态类型而不是相同的结果。我还尝试使用 'ref' 关键字传递委托,以确保我正在存储和引用原始对象而不是本地副本...可能是次要问题,但一次一步。

[更新]

OIC,无法限制 Delegate 类型似乎是这里的一个主要问题,并且像我这样做的方式阻止了泛型使用。感谢您指出罗恩。

澄清原意:
我使用委托来处理内部事件;比严格的“事件”类型更灵活。我正在寻找某种方式在运行时将委托(参考?)传递给 MyWorker 类。然后 MyWorker 执行一些后台任务,这些任务在操作期间根据需要订阅和取消订阅以接收事件,最后退出垃圾收集。我为 30 多个几乎相同的任务/事件执行此操作,这就是为什么非常需要创建可重用(通用?)类的原因。

我系统中的代表具有严格的形式,例如:

delegate void delegateEvent1(Class1 arg);
delegate void delegateEvent2(Class2 arg);
...
delegate void delegateEventN(ClassN arg);

B 计划是通过 Action 委托在 MyWorker 中订阅和取消订阅。这有点麻烦,因为它需要为每次调用创建 2 个 Actions,而不仅仅是干净地传递所需的委托。

欢迎任何建议...

【问题讨论】:

  • 也许你应该在这里解释你想要达到的目标。你的代码没有意义。错误的原因是因为编译器不知道 mDelegate 是什么类型。您可以使用generic type constraint 给它一个提示。但委托不是一种类型。考虑改用 Action 或 Func。
  • 虽然可以将委托用作泛型类型,但不能对其进行约束,因此编译器无法知道 TDelegate 是委托类型,据它所知,它是一个结构或类。请参阅stackoverflow.com/questions/191940/… 之后,您需要在检查委托类型后进行强制转换。

标签: c# delegates ref


【解决方案1】:

这不是因为您将泛型参数命名为 delegateT 编译器知道它是某种委托类型,因此它无法知道该类型上存在某些 += 运算符。 它需要一些通用的约束来强制执行;但是 AFAIK 在 C# 中是不可能的

正如 KiwiPiet 在评论中指出的那样,您也许可以尝试为 some 委托类型添加约束
正如 Ron Beyer 在评论中指出的那样,也不能限制某些委托类型

【讨论】:

  • 您不能为委托类型添加约束,它是您不能约束的少数类型之一(如 Enum)。
  • 我知道委托约束(并说过),但不太确定像 where T : Func&lt;WhatEver&gt; 和 KiwiPiet 评论这样的约束没有帮助,所以我写了它以防万一(可能)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
  • 2013-11-17
  • 1970-01-01
  • 2011-05-29
  • 2016-04-16
  • 1970-01-01
相关资源
最近更新 更多