C# 为什么我必须显式实现object类型的接口成员,而该成员已经用另一种类型实现了?

C# 为什么我必须显式实现object类型的接口成员,而该成员已经用另一种类型实现了?,c#,generics,object,interface,C#,Generics,Object,Interface,考虑以下示例: namespace Test { interface IContract : IContract<object> { } interface IContract<T> { void Definition(T data); } public class SomeClass : IContract, IContract<SomeContractClass> { pu

考虑以下示例:

namespace Test
{
    interface IContract : IContract<object> { }

    interface IContract<T>
    {
        void Definition(T data);
    }

    public class SomeClass : IContract, IContract<SomeContractClass>
    {
        public void Definition(SomeContractClass data)
        {
            // ...
        }
    }

    public class SomeContractClass { }
}
名称空间测试
{
接口IContract:IContract{}
接口IContract
{
空洞定义(T数据);
}
公共类SomeClass:IContract,IContract
{
公共void定义(SomeContractClass数据)
{
// ...
}
}
公共类{}
}
我想我应该通过提供
定义(SomeContractClass数据)
来满足接口,因为如中所述:

在C#的统一类型系统中,所有类型、预定义类型和 用户定义的引用类型和值类型,直接继承或 间接来自对象

但是编译器要求我显式地定义它:

错误1“Test.SomeClass”未实现接口成员 '测试.IContract.Definition(对象)'


您正在实现接口
IContract

如果我们将继承继承权扁平化,我们可以看到
IContract
基本上如下所示:

interface IContract
{
    void Definition(object data);
}
您没有提供与签名
无效定义(对象数据)
匹配的方法-您提供的方法采用
SomeContractClass
。因此,您会收到声明的错误消息


但是,我认为潜在的问题是,您的类同时实现了
IContract
IContract
(这与说
IContract
IContract
相同)。我认为你的设计需要做一些工作…

我将对你的情况做一个小小的类比

你们有一家修理小型汽车的小公司

您与政府签订合同,政府需要为其外交车队中的任何类型的车辆(飞机、船只、大卡车和小型汽车)提供维修服务

你一做出概括就撒了谎/犯了一个小错误

1) 既然你成功地实现了

void Repair(SmallCar vehicle) 
2) 因为

class SmallCar : Vehicle { }
class Airplane : Vehicle { }
class Boat : Vehicle { }
class BigTruck : Vehicle { }
不知何故,点(1+2)=>点3的组合表示:

3) 政府可以放心地称你的小公司为“修理任何东西的人”,并且 总有一天,请你的公司帮助他们这样做是个好主意:

Airplane protocolPlane = new Airplane();
yourCompany.Repair(protocolPlane);
这当然不是真的:(1+2)并不意味着(3)

这是一件好事,它最终成为一个编译器错误,而不是运行时异常。这样,您可以更快地了解体系结构中的一个小问题

编辑

在您的代码中,如果您决定确实需要在SomeClass类中实现这两个接口,并且您不知道如何实现,那么可以使用如下显式接口实现:

public class SomeClass : IContract, IContract<SomeContractClass>
{
    // Method of IContract<SomeContractClass>
    public void Definition(SomeContractClass data)
    {
        Console.WriteLine("Processing a SomeContractClass instance");            
        // ...etc
    }
    // Method of IContract hence of IContract<object>
    void IContract<object>.Definition(object data)
    {
        if (data is SomeContractClass)
          this.Definition(data as SomeContractClass);
        else
        {
          string descriptor = (null == data) 
            ? "A null reference" 
            : "An instance of " + data.GetType().Name";
          Console.WriteLine("Processing something other than a SomeContractClass instance: " + descriptor);
          // ...etc
        }
    }

}
public类SomeClass:IContract,IContract
{
//合同法
公共void定义(SomeContractClass数据)
{
WriteLine(“处理SomeContractClass实例”);
//…等等
}
//合同法
void IContract.Definition(对象数据)
{
if(数据为SomeContractClass)
定义(数据作为SomeContractClass);
其他的
{
字符串描述符=(空==数据)
?“空引用”
:“一个“+data.GetType().Name”的实例”;
WriteLine(“处理SomeContractClass实例以外的其他对象:“+描述符”);
//…等等
}
}
}
这样,您将成功获得以下结果:

class Program {
     public static void Main(string[] args) {
         SomeClass someInstance = new SomeClass();
         IContract<SomeContractClass> first= someInstance;
         IContract second = someInstance;

         someInstance.Definition(new SomeContractClass()); 
         // prints out "Processing a SomeContractClass instance"

         first.Definition(new SomeContractClass());
         // prints out "Processing a SomeContractClass instance"

         second.Definition(new SomeContractClass());
         // prints out "Processing a SomeContractClass instance"

         second.Definition( "something else" );
         // prints "Processing something other 
         // than a SomeContractClass instance: An instance of String"

         second.Definition( 123 );
         // prints "Processing something other
         // than a SomeContractClass instance: An instance of Int32"

         first.Definition( true );
         // doesn't compile saying that bool can't be converted to SomeContractClass

     }
}
类程序{
公共静态void Main(字符串[]args){
SomeClass someInstance=新的SomeClass();
IContract first=某个实例;
IContract second=某个实例;
定义(新的SomeContractClass());
//打印“处理SomeContractClass实例”
首先,定义(新的SomeContractClass());
//打印“处理SomeContractClass实例”
定义(新的SomeContractClass());
//打印“处理SomeContractClass实例”
第二,定义(“其他事物”);
//打印“处理其他内容”
//而不是SomeContractClass实例:字符串“”的实例
第二,定义(123);
//打印“处理其他内容”
//而不是SomeContractClass实例:Int32的实例”
第一,定义(正确);
//编译时没有说bool不能转换为SomeContractClass
}
}

编辑结束

如果这是一个愚蠢的问题,请提前道歉,我花了一段时间才想出标题,这可能使我无法在发布问题之外找到解决方案。您没有为IContract实现任何功能?看起来有一个公共空白定义(对象数据)或者类似的东西?很好的类比,但我想你指的是
无效维修(车辆)
,而不是
小型车
。谢谢,也许我表达得不够清楚。我想说的是:虽然事实上,“公司”只为小型车提供维修服务(不是任何东西)它正试图签署一份合同,声明他们可以处理任何事情……因此,我写“SmallCar”而不是“Vehicle”的地方不是合同,而是实际情况(这与合同相矛盾)@RB:btw,很抱歉没有停止写我的小比喻,尽管我注意到“某人”已经回答了(当ajax通知出现的时候,我有这么大的动力,我就是停不下来:)你有我的投票:)@RB:我对答案进行了编辑。希望它现在更清晰了…:)谢谢你的时间回答,现在更清晰了。我专注于使用,界面非常难(!)合同-我需要满足签名。关于“设计”你是对的,它需要ctrl+a然后del。我在玩和en