实现通用接口时奇怪的C#行为

约恩·怀尔德

给定此“ IHandle”接口和两个要处理的类:

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”,因此无法编译,因此输出:

错误CS0695:“ HandlerBase”无法同时实现“ IHandle”和“ IHandle”,因为它们可能会为某些类型参数替换统一

这本身有点奇怪,因为我看不到T可能是MReset类型,因为T必须是M1类型。但是好吧,我可以接受编译器比我更聪明:-)

编辑:编译器并不比我更聪明:-)根据关于为什么在CS0695中导致此结果的注释。我们有“在确定所有可能的构造类型时不考虑约束声明”。

现在,我交换接口声明:

class HandlerBase<T> :
  IHandle<T> where T : M1,
  IHandle<MReset>
{
  ... same as before ..
}

突然,我收到一条不同的错误消息,指出我无法实现IHandle.Handle(MReset m),因为类声明未声明其正在实现该接口:

错误CS0540:“ HandlerBase.IHandle <...>。Handle(MReset)”:包含类型未实现接口“ IHandle”

问题:为什么声明顺序会产生不同的影响?第二个示例出了什么问题?

最后,有一个解决方案:

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>通用接口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 ..
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C#对象修改:奇怪的行为

来自分类Dev

奇怪的C#平台调用/ DLLImport行为

来自分类Dev

在C#通用接口中实现通用C ++ / CLI接口

来自分类Dev

接口实现上的C#行为

来自分类Dev

C#中通用接口的简写语法

来自分类Dev

C#中奇怪的Regex行为

来自分类Dev

接口中的C#多层通用类型

来自分类Dev

多线程行为奇怪的C#!

来自分类Dev

通用接口的非通用实现

来自分类Dev

奇怪的BeginInvoke行为C#

来自分类Dev

将C#对象作为通用接口

来自分类Dev

实现通用接口和非通用接口

来自分类Dev

通用接口缺少实现

来自分类Dev

在C#中实现接口的通用方法时,出现了奇怪的错误。这到底是怎么了?

来自分类Dev

在实现通用接口C#的通用类中修改值类型

来自分类Dev

C#泛型:实现符合通用接口协定的通用类时,CS0311

来自分类Dev

在C#通用接口中实现通用C ++ / CLI接口

来自分类Dev

接口实现上的C#行为

来自分类Dev

在C#中实现通用接口

来自分类Dev

C#下载奇怪的行为

来自分类Dev

在C#中使用通用类型实现接口的类的工厂?

来自分类Dev

通用接口的非通用实现

来自分类Dev

将C#对象作为通用接口

来自分类Dev

实现通用接口和非通用接口

来自分类Dev

锁定C#:奇怪的行为

来自分类Dev

C#字典的奇怪行为

来自分类Dev

C#类的工厂,实现通用接口

来自分类Dev

通用接口的多种实现

来自分类Dev

C# 实现事件接口