假设你有这个:
// 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();
}
}
Run Code Online (Sandbox Code Playgroud)
为什么在这个世界上我得到这个编译错误?我尊重界面 - 事实上,我确实返回了IDataResult,尽管是间接的.是编译器无法解决这个问题还是从根本上(在OO级别)出现了错误的问题,在这里?
我认为拥有一个接口的全部意义在于我可以保证一些实现,但是让它为我添加它.这就是我正在做的 - 但我得到一个编译错误.
在我的实际代码中,我希望返回类型更具体,因为我在派生接口中有几个额外的方法.如果我创建类型为IDataResult的MyCrazySerializer.Serialize的返回类型,那么intellisense只显示我和简单的常用方法,我想在其中显示更具体的接口.
我怎么能做到这一点?这段代码有什么问题?
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);
}
}
Run Code Online (Sandbox Code Playgroud)
正如评论所指出的那样,您可以在显式实现中调用更具体的版本.
你可以用作:
IMyCrazyDataResult result = new MyCrazySerializer().Serialize<int>(1);
ISerializer serializer = (ISerializer)new MyCrazySerializer();
IDataResult = serializer.Serialize<int>(1);
Run Code Online (Sandbox Code Playgroud)
您可以在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();
}
}
Run Code Online (Sandbox Code Playgroud)
Serialize明确声明返回类型是源自IDataResult而不是精确的TResult.