接口实现混乱

时间:2012-07-21 19:21:15

标签: c# oop interface

假设你有这个:

// General purpose
public interface ISerializer
{
    IDataResult Serialize<T>(T instance);
}

// General purpose
public interface IDataResult
{
}

// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}

public class MyCrazySerializer : ISerializer
{
    // COMPILE ERROR:
    // error CS0738: 'MyCrazySerializer' does not implement interface member 'ISerializer.Serialize<T>(T)'. 
    // 'MyCrazySerializer.Serialize<T>(T)' cannot implement 'ISerializer.Serialize<T>(T)' because it does 
    // not have the matching return type of 'IDataResult'.
    public IMyCrazyDataResult Serialize<T>(T instance)
    {
        throw new NotImplementedException();
    }
}

为什么我在世界上遇到这个编译错误?我尊重界面 - 事实上,我确实返回了IDataResult,尽管是间接的。难道编译器无法解决这个问题,或者是否存在根本(在OO级别)错误的问题,在这里?

我认为拥有接口的全部意义在于我可以保证一些实现,但是让它为我添加它。这就是我正在做的 - 但我得到一个编译错误。

在我的实际代码中,我希望返回类型更具体,因为我在派生接口中有几个额外的方法。如果我做了类型IDataResult的MyCrazySerializer.Serialize的返回类型,那么intellisense只显示我和简单的常用方法,我想要显示更具体的界面。

我怎么能做到这一点?这段代码有什么问题???

5 个答案:

答案 0 :(得分:5)

C#不支持return type covariance,因此您需要完全按照界面上显示的方式实施Serialize<T>方法。您可以明确地实现它,这意味着任何知道MyCrazySerializer实际类型的客户端都可以访问更具体的方法:

public class MyCrazySerializer : ISerializer
{
    public IMyCrazyDataResult Serialize<T>(T instance)
    {
        throw new NotImplementedException();
    }

    IDataResult ISerializer.Serialize<T>(T instance)
    {
        return this.Serialize(instance);
    }
}

正如评论所指出的那样,您只需在显式实现中调用更具体的版本。

您可以将其用作:

IMyCrazyDataResult result = new MyCrazySerializer().Serialize<int>(1);
ISerializer serializer = (ISerializer)new MyCrazySerializer();
IDataResult = serializer.Serialize<int>(1);

答案 1 :(得分:5)

您可以在C#中构建自己的返回类型协方差:

// General purpose
public interface ISerializer<out TResult> where TResult : IDataResult
{
    TResult Serialize<T>(T instance);
}

// General purpose
public interface IDataResult
{
}

// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}

public class MyCrazySerializer : ISerializer<IMyCrazyDataResult>
{
    public IMyCrazyDataResult Serialize<T>(T instance)
    {
        throw new NotImplementedException();
    }
}

明确声明Serialize的返回类型来自IDataResult,而不是TResult

答案 2 :(得分:3)

  

为什么我在世界上遇到这个编译错误?我尊重界面

不,你不是。您没有返回IDataResult,而是IMyCrazyDataResult。是的,它继承自IDataResult,但不相同。

说到接口,你不会得到差异 - 类型必须完全匹配。

答案 3 :(得分:3)

您没有充分了解接口合约,因为您指定了不同的方法作为方法的返回类型,签名必须完全匹配。这并不意味着你不能返回更多指定的接口,以下是完全正常的:

// General purpose
public interface ISerializer
{
    IDataResult Serialize<T>(T instance);
}

// General purpose
public interface IDataResult
{
}

// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}

public class MyCrazySerializer : ISerializer
{
    public IDataResult Serialize<T>(T instance)
    {
        // return a IMyCrazyDataResult here
    }
}

答案 4 :(得分:1)

与C ++不同,C#没有covariant return type