给定此“IHandle”接口(interface)和两个要处理的类:
interface IHandle<T>
{
void Handle(T m);
}
class M1
{
public int Id;
}
class MReset
{
}
我想创建一个通用的基础来处理“重置”以及管理M1实例:
class HandlerBase<T> :
IHandle<MReset>,
IHandle<T> where T : M1
{
protected int Count;
void IHandle<T>.Handle(T m)
{
++Count;
Console.WriteLine("{0}: Count = {0}", m.Id, Count);
}
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
}
}
由于编译器认为T可能是“MReset”,因此无法编译,因此输出:
这本身有点奇怪,因为我看不到T可能是MReset类型,因为T必须是M1类型。但是好吧,我可以接受编译器比我更聪明:-)
编辑:编译器并不比我聪明:-)根据对Why does this result in CS0695?的评论,我们有“在确定所有可能的构造类型时不考虑约束声明”。
现在,我交换接口(interface)声明:
class HandlerBase<T> :
IHandle<T> where T : M1,
IHandle<MReset>
{
... same as before ..
}
突然,我收到一条不同的错误消息,指出我无法实现IHandle.Handle(MReset m),因为类声明未声明其正在实现该接口(interface):
问题:为什么声明顺序会产生这样的差异?第二个示例出了什么问题?
最后,有一个解决方案:
class HandlerBase :
IHandle<MReset>
{
protected int Count;
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
}
}
class Handler<T> : HandlerBase,
IHandle<T> where T : M1
{
void IHandle<T>.Handle(T m)
{
++Count;
Console.WriteLine("{0}: Count = {0}", m.Id, Count);
}
}
但是,该解决方案仅在
HandlerBase
实现IHandle<MReset>
的情况下有效-如果通用接口(interface)IHandle<T>
首先在HandlerBase
中实现,则该解决方案不起作用。 为什么选择?编辑:在
IHandle<T>
中实现HandlerBase
确实可行(如果我已经显示了代码,则可能有人看到过)。这有效:class HandlerBase<T> :
IHandle<T> where T : M1
{
protected int Count;
void IHandle<T>.Handle(T m)
{
++Count;
Console.WriteLine("Type = {0}, Id = {1}, Count = {2}", GetType(), m.Id, Count);
}
}
class Handler<T> : HandlerBase<T>,
IHandle<MReset>
where T : M1
{
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
Console.WriteLine("RESET");
}
}
不幸的是,我的第二堂课声明是这样的:
class Handler<T> : HandlerBase<T> where T : M1,
IHandle<MReset>
{
void IHandle<MReset>.Handle(MReset m)
{
Count = 0;
Console.WriteLine("RESET");
}
}
请注意
where T : M1
位置的细微差别:-)最后一个示例声明T必须实现IHandle<MReset>
(除了M1
之外)。 h! 最佳答案
问题已解决-我发现了细微的差别。当声明的顺序交换时,我不应该移动where T : M1
,因为IHandle<MReset>
约束然后最终应用于T而不是类声明:
class HandlerBase<T> :
IHandle<T> where T : M1,
IHandle<MReset>
{
... same as before ..
}
正确的重新排序应该是:
class HandlerBase<T> :
IHandle<T>,
IHandle<MReset>
where T : M1
{
... same as before ..
}