[英]How to implement a generic method that returns a specific type on an interface in C#
[英]How to implement this generic interface for this C# method
我有以下界面:
public interface ICopyable
{
void Copy<T>(T source) where T : class;
}
我试图实现它,但我不断收到此错误:
方法 'Foo.Core.Models.AggregateRoot.Copy(TListing)' 的类型参数 'TListing' 的约束必须匹配接口方法 'FooCore.Interfaces.ICopyable.Copy(T)' 的类型参数 'T' 的约束。 考虑改用显式接口实现。
public abstract class AggregateRoot : ICopyable
{
public virtual void Copy<TListing>(TListing newAggregateRoot)
where TListing : AggregateRoot
{
// my code here.
}
}
为什么会失败? 我的AggregateRoot
是一个类。
假设您的代码已编译。 然后你可以这样做:
class Derived : AggregateRoot
{
}
进而:
var derived = new Derived();
ICopyable copyable = derived;
copyable.Copy<string>("Hello!");
这很好,因为ICopyable.Copy<T>
需要一个类的类型参数 - 而string
是一个类。 但是它必须被分派到一个实际需要一个T : AggregateRoot
的方法T : AggregateRoot
。 这将不得不在运行时失败 - 因此编译器只是事先拒绝它。
更笼统地说,问题在于您正在尝试使用比接口所说的更严格的实现来实现特定的接口。 这不是类型安全的 - 它会违反关于输入逆变的Liskov 替换原则。
但是即使它是类型安全的并且没有违反 LSP,它仍然会被编译器拒绝。 C# 要求专门化一个类并实现一个接口总是用精确的、不变的签名和相同的约束来完成。 这在C# 规范中的13.4.3 泛型方法的实现中有详细说明:
当泛型方法隐式实现接口方法时,为每个方法类型参数给出的约束必须在两个声明中等效 [...]
但是,C# 仍然允许泛型接口(具有相同泛型类型定义)之间的隐式转换存在差异。 因此,如果将代码更改为以下内容,您的代码将可以正常工作:
public interface ICopyable<in T>
where T : class
{
void Copy(T source);
}
public abstract class AggregateRoot : ICopyable<AggregateRoot>
{
public virtual void Copy(AggregateRoot newAggregateRoot)
{
// my code here.
}
}
现在您可以执行以下操作,它可以编译并且是类型安全的:
var derived = new Derived();
ICopyable<AggregateRoot> aggregateCopyable = derived;
ICopyable<Derived> derivedCopyable = aggregateCopyable;
derivedCopyable.Copy(derived);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.