简体   繁体   English

接口实现混乱

[英]Interface implementation confusion

Assume you have this: 假设你有这个:

// 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();
    }
}

Why in the world do I get this compile error? 为什么在这个世界上我得到这个编译错误? I am respecting the interface - I do, in-fact, return an IDataResult, albeit indirectly. 我尊重界面 - 事实上,我确实返回了IDataResult,尽管是间接的。 Is it that the compiler can't figure that out or is there something fundamentally (at an OO level) wrong, here? 是编译器无法解决这个问题还是从根本上(在OO级别)出现了错误的问题,在这里?

I thought the entire point of having an interface was that I could guarantee some implementation, but leave it open for me to add-on to it. 我认为拥有一个接口的全部意义在于我可以保证一些实现,但是让它为我添加它。 That is what I am doing - yet I get a compile error. 这就是我正在做的 - 但我得到一个编译错误。

In my real code, I want the return type to be a bit more specific because I have several additional methods that I have in my derived interface. 在我的实际代码中,我希望返回类型更具体,因为我在派生接口中有几个额外的方法。 If I make the return type of MyCrazySerializer.Serialize of-type IDataResult, then intellisense just shows me and the bare-bones common methods, where I want to show a more-specific interface. 如果我创建类型为IDataResult的MyCrazySerializer.Serialize的返回类型,那么intellisense只显示我和简单的常用方法,我想在其中显示更具体的接口。

How else could I accomplish this? 我怎么能做到这一点? What is wrong with this code??? 这段代码有什么问题?

C# does not support return type covariance so you'll need to implement the Serialize<T> method exactly as it appears on the interface. C#不支持返回类型协方差,因此您需要完全按照界面上显示的方式实现Serialize<T>方法。 You could implement it explicitly however, meaning any clients which know the real type of MyCrazySerializer can access the more specific method: 您可以明确地实现它,这意味着任何知道MyCrazySerializer真实类型的客户端都可以访问更具体的方法:

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

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

As the comment point out, you can simply call the more specific version in your explicit implementation. 正如评论所指出的那样,您可以在显式实现中调用更具体的版本。

Which you can use as: 你可以用作:

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

You can build your own kind of return type covariance in C#: 您可以在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();
    }
}

The return type of Serialize is explicitly stated to be something that derives from IDataResult , instead of being precisely TResult . Serialize的返回类型明确声明是从IDataResult派生的,而不是精确的TResult

Why in the world do I get this compile error? 为什么在这个世界上我得到这个编译错误? I am respecting the interface 我尊重界面

No, you are not. 不,你不是。 You are not returning a IDataResult , but a IMyCrazyDataResult . 您没有返回IDataResult ,而是返回IMyCrazyDataResult Yes, it inherites from IDataResult , but it isn't identical to it. 是的,它从inherites IDataResult ,但它等同于它。

When it comes to interfaces, you don't get variance - types must match exactly. 说到接口,你不会得到差异 - 类型必须完全匹配。

You aren't fulfulling the interface contract, as you specify something different as the return type of the method, the signatures have to match completely. 您没有充分了解接口契约,因为您指定了不同的方法作为方法的返回类型,签名必须完全匹配。 This doesn't mean you can't return the more specified interface, the following is perfectly fine: 这并不意味着你不能返回更多指定的接口,以下是完全正常的:

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

与C ++不同,C#没有协变返回类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM