首页 > 解决方案 > C#泛型类继承混淆

问题描述

abstract class BaseClassA{}

class DerivedClassA : BaseClassA{}

abstract class BaseClassB<T> where T : BaseClassA
{    
  public T foo;
}

class DerivedClassB : BaseClassB<DerivedClassA>
{
  public DerivedClassB(DerivedClassA _foo)
  {
    foo = _foo;
  }
}

class Test
{
  DerivedClassB foobar = new DerivedClassB();
  void main()
  {
    //Error: casting not possible
    BaseClassA<BaseClassB> bar = new DerivedClassA<DerivedClassB>(foobar);
  }
}

嘿大家。我有一个小问题。上面的代码给了我一个“无法转换”的异常。我希望能够访问 DerivedClassB 的 foo,而无需将其从 BaseClassA 转换为 DerivedClassA。

我不能有一个从基类派生的泛型类型并且仍然使用它吗?

标签: c#genericsinheritance

解决方案


问题是,如果您想要的是合法的,那么这也是合法的:

abstract class Animal {}
class Goldfish : Animal {}
class Giraffe : Animal {}
abstract class Cage<T> where T : Animal {
   void Add(T newAnimal) { ... }
}
class Aquarium : Cage<Goldfish> { }
...
Cage<Animal> c = new Aquarium(); // This is not legal, but suppose it was
c.Add(new Giraffe()); // A giraffe is an animal

现在我们在水族馆里养了一只长颈鹿,没有人高兴。

此功能称为协变,它仅适用于泛型接口和委托,当它们使用引用类型构造时,它们专门设计用于处理方差并由编译器检查安全性

例如,您可以在预期 anIEnumerable<Fish>的上下文中使用 an,IEnumerable<Animal>因为无法将长颈鹿添加到动物序列中。

我不能有一个从基类派生的泛型类型并且仍然使用它吗?

是的,但你必须遵守规则。这些规则是为了保证你的安全。了解类型系统如何工作并使用它来帮助防止您的错误,您将永远不会错误地将长颈鹿放入水族箱。


推荐阅读