不能使用从具有指定类型的泛型类继承的非泛型类的实例变量

时间:2014-12-16 09:55:30

标签: c# .net

我创建了这样的类:

abstract class AClass1<T>
{
    // some code here
}

class Class2 : AClass1<int>
{
    // some code here
}

class Class3 : AClass1<float>
{
    // some code here
}

class Class4<T> : AClass1<T>
{
    // some code here
}

到目前为止它的确有效。但在另一个课程中,我希望:

...
AClass1<T> variable;

并根据具体需要将变量设置为:

variable = new Class2();

variable = new Class3();

或有时:

variable = new Class4<T>();

这会产生编译错误,没有可能的强制转换或我尝试过的任何其他内容。目前我只是将所有继承类更改为泛型,如:

class Class2<T> : AClass1<T>
{
    // some code here
}

但感觉不对,因为那里没有通用的方法或任何东西。

问题是什么是正确的方法,为什么,为什么我不能用我原来的方式做到这一点?

顺便说一下,这是.net 2.0,因为我在Unity3D中这样做。

更清楚:

我有一些特殊情况,例如对于我想要专门处理的int类型,但还有其他我希望有一个泛型类。所以我创建了一些特定处理某些类型的子类,并且我还有一个通用子类,当没有特定的类型实现时我会使用它。当我为一个类型创建一个特定的类时,它不应该是通用的,因为它只处理一种类型。

2 个答案:

答案 0 :(得分:1)

Class2对象无法分配给AClass1<T>变量,因为Class2不是来自AClass1<T>,而是来自AClass1<int>。这些是不兼容的类型,编译器无法在它们之间进行转换。因此编译错误。

也许您可以为AClass1<T>引入非通用基类?

答案 1 :(得分:1)

编译器正在尝试通过确保您不执行无法保证工作的分配来帮助您。这不合法:

void foo<T>() {
  ...
  if (typeof(T) == typeof(int)) {
    AClass1<T> variable = new Class2();
  }
  ...
}

那是因为Class2只与AClass1<int>兼容 - 如果我们不知道T是什么,我们通常不能说它与AClass1<T>兼容。在上面的代码中,确定转换是可能的,但是编译器不够复杂,无法确定此代码是否安全 - 通常,如果没有if,它就不会#39}是的。投射也不起作用,因为任意Class2都没有从AClass1<T>转换为T

为了完成这项工作,你必须放弃编译时类型检查并强制进行运行时转换 - 在编译时转换成Object总是合法的:

    AClass1<T> variable = (AClass1<T>) (object) new Class2();

如果你弄错了,代码将在运行时失败InvalidCastException

这种方法很可疑,因为它提出了为什么使用泛型(编译时类型特性)然后在实际代码中绕过它们的问题。像这样的代码必须仔细审查,看看这是否真的是最合适的解决方案。可能的替代方法是引入非泛型基类,使用包含泛型类型,或者根本不使用泛型(如果您真的只使用floatint,则是通用基类添加什么?)