我不明白为什么这不起作用:
类:
public abstract class BaseObj
{
public bool IsValid => GetValidationErrors().Count == 0;
}
public class BaseObjWithId: BaseObj
{
public int Id { get; set; }
}
public class BaseReference<T> : BaseObj where T : BaseObjWithId
{
public T ObjReference { get; set; }
}
public class Foo: BaseObjWithId
{
public string Name{get;set;}
}
public class FooRef : BaseReference<Foo>
{
}
代码语句:
BaseReference<BaseObjWithId> foo= new FooRef();
错误CS0029无法隐式转换类型...
这有效:
BaseReference<Foo> foo= new FooRef();
但我不明白为什么,因为Foo是一个BaseObjWithId ......
感谢您的解释
答案 0 :(得分:1)
您误解了泛型在类型继承方面的工作原理。您可以将FooRef
类型的对象强制转换为BaseReference<Foo>
类型的引用,因为FooRef
继承自BaseReference<Foo>
。但是,您不能将BaseReference<Foo>
强制转换为BaseReference<BaseObjWithID>
,因为与它们用作泛型类型参数的类型不同,这两个泛型类没有这样的连接。
采用以下示例:
public class Fruit {}
public class Apple : Fruit {}
任何Apple
对象都可以存储在Fruit
引用中,因为继承可以确保它们之间的关系检出:
Fruit f = new Apple();
但是,在涉及泛型的情况下,每次使用不同的类型参数创建类的泛型版本时,这些版本都被视为完全不同的类型。例如,虽然上面的隐式转换会起作用,但以下内容将失败:
List<Fruit> f = new List<Apple>();
List<Fruit>
和List<Apple>
是完全不同的类。它们之间没有隐式或明确的直接转换。
答案 1 :(得分:1)
您在搜索什么,名为covariance
。在你的情况下 - 泛型的协方差。根据{{3}},它仅适用于有限的类型集:
这很好用:
IEnumerable<Derived> b = new List<Derived>();
IEnumerable<Base> a = b;
这不起作用:
IList<Derived> b = new List<Derived>();
IList<Base> a = b;
因此,在您的情况下,FooRef
直接来自BaseReference<Foo>
,因此可以将其转换为此类型,而c#不能简单地将BaseReference<Foo>
转换为BaseReference<BaseObjWithId>
因为泛型参数协方差的问题。
可能有一些变通方法,分离的方法,从一种类型到另一种类型的硬编码转换,但是,我想,应该避免这种行为。