4

假设你有这个:

// 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级别)有什么问题?

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

在我的真实代码中,我希望返回类型更具体一点,因为我在派生接口中有几个附加方法。如果我将 MyCrazySerializer.Serialize 的返回类型设为 IDataResult 类型,那么智能感知只会向我显示基本的常用方法,我想在其中显示更具体的接口。

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

4

5 回答 5

5

C# 不支持返回类型协方差,因此您需要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);
于 2012-07-21T19:26:27.613 回答
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

于 2012-07-21T19:28:34.577 回答
3

为什么我会得到这个编译错误?我尊重界面

不,你不是。你不是返回一个IDataResult,而是一个IMyCrazyDataResult。是的,它继承自IDataResult,但与它不同

当涉及到接口时,您不会得到差异 - 类型必须完全匹配。

于 2012-07-21T19:24:53.067 回答
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
    }
}
于 2012-07-21T19:26:12.320 回答
1

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

于 2012-07-21T19:26:20.773 回答