【发布时间】:2011-09-26 03:38:09
【问题描述】:
下面的代码显示了一个具有类型约束 (Pub<T>) 的泛型类。该类有一个可以引发的事件,允许我们将消息传递给订阅者。约束是消息必须实现IMsg(或者当它是抽象类时从IMsg继承)。
Pub<T> 还提供了一个Subscribe 方法,当且仅当对象实现IHandler<IMsg> 时,才允许对象订阅notify 事件。
使用 .NET 4,以下代码在 baseImplementer.NotifyEventHandler 上显示错误,指出:"No overload for 'IHandler<IMsg>.NotifyEventHandler(IMsg)' matches delegate 'System.Action<T>'"
问题:(使用更新的订阅方法)
为什么我将 `IMsg` 更改为抽象类而不是接口后,错误就消失了?
public interface IMsg { } // Doesn't work
//public abstract class IMsg { } // Does work
public class Msg : IMsg { }
public class Pub<T> where T : IMsg
{
public event Action<T> notify;
public void Subscribe(object subscriber)
{
// Subscriber subscribes if it implements IHandler of the exact same type as T
// This always compiles and works
IHandler<T> implementer = subscriber as IHandler<T>;
if (implementer != null)
this.notify += implementer.NotifyEventHandler;
// If subscriber implements IHandler<IMsg> subscribe to notify (even if T is Msg because Msg implements IMsg)
// This does not compile if IMsg is an interface, only if IMsg is an abstract class
IHandler<IMsg> baseImplementer = subscriber as IHandler<IMsg>;
if (baseImplementer != null)
this.notify += baseImplementer.NotifyEventHandler;
}
}
public interface IHandler<T> where T : IMsg
{
void NotifyEventHandler(T data);
}
这里的代码不是重现问题所必需的......但显示了如何使用上面的代码。显然IMsg(以及派生的Msg)类将定义或实现可以在处理程序中调用的方法。
public class SubA : IHandler<Msg>
{
void IHandler<Msg>.NotifyEventHandler(Msg data) { }
}
public class SubB : IHandler<IMsg>
{
void IHandler<IMsg>.NotifyEventHandler(IMsg data) { }
}
class MyClass
{
Pub<Msg> pub = new Pub<Msg>();
SubA subA = new SubA();
SubB subB = new SubB();
public MyClass()
{
//Instead of calling...
this.pub.notify += (this.subA as IHandler<Msg>).NotifyEventHandler;
this.pub.notify += (this.subB as IHandler<IMsg>).NotifyEventHandler;
//I want to call...
this.pub.Subscribe(this.subA);
this.pub.Subscribe(this.subB);
//...except that the Subscribe method wont build when IMsg is an interface
}
}
【问题讨论】:
-
如果你在 Pub 类中为 T 添加 class 约束,它会编译,但我知道为什么。
-
呃,我的意思是我“不”知道为什么。这可能很明显。 :)
-
@Charles:很好的观察。请参阅我的答案以获得解释。
-
@Charles... 我误解了您最初的评论。好的电话虽然。有了 Eric 的解释……现在说得通了。
标签: c# generics interface abstract-class constraints