给定此“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 ..
}

07-28 00:46