奇怪的泛型编译错误

5
我有两个类,一个是基类,一个是子类。在基类中,我定义了一个通用的虚方法:
protected virtual ReturnType Create<T>() where T : ReturnType {}
然后在我的子类中,我试图这样做:
protected override ReturnTypeChild Create<T>() // ReturnTypeChild 继承自 ReturnType
{ 
  return base.Create<T> as ReturnTypeChild; 
}
Visual Studio 给出了一个奇怪的错误:
The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Create()'. There is no boxing conversion or type parameter conversion from 'T' to 'ReturnType'.
在子类的重写中重复使用 where 子句也会导致错误:
Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly
那么我在这里做错了什么?

这个应该改成 protected override BarChild Foo<T>() 吧?能不能用更合适的名字?Foo 和 Bar 让我很困惑。 - Kobi
难道不应该返回 base.Foo<T> 作为 BarChild() 吗? - djdd87
1
你的代码存在各种问题(例如,你重写的方法缺少泛型参数,你的返回语句中括号位置错误等)。如果你能创建一个修复了所有明显问题的最小化问题复现,那么你更有可能得到有帮助的答案。 - kvb
好的,我修好了一切 :) 那么,有人吗? - Jouke van der Maas
C#不支持虚拟返回类型协变。也就是说,当你重写一个方法时,返回类型必须完全匹配。你不能有虚拟的Mammal M(),然后用override Cat M()来覆盖它。 - Eric Lippert
显示剩余3条评论
2个回答

3
这个可以运行。您需要将返回类型设置为通用类型:
public class BaseClass {
  public virtual T Create<T>() where T : BaseClass, new()  {
   var newClass = new T();
   //initialize newClass by setting properties etc
   return newClass;
  }
 }

 public class DerivedClass : BaseClass {
  public override T Create<T>() {
   var newClass =  base.Create<T>();
   //initialize newClass with DerivedClass specific stuff
   return newClass;
  }
 }

void Test() {

 DerivedClass d = new DerivedClass() ;
 d.Create<DerivedClass>();
}

以下是一些基本的C# 重写规则

被重写的基方法必须与重写方法具有相同的签名。

这意味着相同的返回类型和相同的方法参数。


你能再编辑一次吗?据我所知,这些类需要缩进以正确格式化。 - James Manning

2

即使返回类型从基类方法的返回类型派生,您的重写也不能更改返回类型。您需要像上面的Igor所做的那样,使返回类型成为通用类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接