当成员已经用另一种类型实现时,为什么必须显式实现object类型的接口成员?

时间:2013-02-26 14:06:36

标签: c# generics object interface

考虑以下示例:

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 { }
}

由于MDSN中所述,我认为我会通过提供Definition(SomeContractClass data)来满足界面:

  

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

但是编译器要求我明确定义它:

  

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

2 个答案:

答案 0 :(得分:8)

您正在实施界面IContract

如果我们将继承heirarchy展平,我们可以看到IContract基本上是这样的:

interface IContract
{
    void Definition(object data);
}

您没有提供与签名void Definition (object data)匹配的方法 - 您提供的方法需要SomeContractClass。因此,您会收到声明的错误消息。

但是,我认为潜在的问题是您的类实现了IContractIContract<T>(这与说IContract<object>IContract<T>相同)。我认为你的设计需要一些工作......

答案 1 :(得分:3)

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

你有一家小公司在维修小型车。

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

当你进行概括时,你撒了一个小错误

1)因为你成功实施了

void Repair(SmallCar vehicle) 

2)因为

class SmallCar : Vehicle { }
class Airplane : Vehicle { }
class Boat : Vehicle { }
class BigTruck : Vehicle { }

以某种方式,点(1 + 2)的组合=&gt;第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
        }
    }

}

这样,您将成功获得以下结果:

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

     }
}

END OF EDIT