理解C#和#x27;s型转换
我不明白为什么这不起作用: 课程:理解C#和#x27;s型转换,c#,C#,我不明白为什么这不起作用: 课程: 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 : Ba
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>
{
}
公共抽象类BaseObj
{
public bool IsValid=>GetValidationErrors()。计数==0;
}
公共类BaseObjWithId:BaseObj
{
公共int Id{get;set;}
}
公共类BaseReference:BaseObj,其中T:BaseObjWithId
{
公共T对象引用{get;set;}
}
公共类Foo:BaseObjWithId
{
公共字符串名称{get;set;}
}
公共类FooRef:BaseReference
{
}
代码声明:
BaseReference<BaseObjWithId> foo= new FooRef();
BaseReference foo=new FooRef();
错误CS0029无法隐式转换类型
这项工作:
BaseReference<Foo> foo= new FooRef();
BaseReference foo=new FooRef();
但我不明白为什么,因为Foo是一个BaseObjWithId
感谢您的解释您误解了泛型与类型继承的关系。您可以将
FooRef
类型的对象强制转换为BaseReference
类型的引用,因为FooRef
继承自BaseReference
。但是,不能将BaseReference
强制转换为BaseReference
,因为与它们用作泛型类型参数的类型不同,这两个泛型类没有这样的连接
以以下为例:
public class Fruit {}
public class Apple : Fruit {}
任何Apple
对象都可以存储在Fruit
引用中,因为继承可以确保它们之间的关系签出:
Fruit f = new Apple();
但是,在涉及泛型的情况下,每次使用不同的类型参数创建类的泛型版本时,这些版本都被视为完全不同的类型。例如,虽然上述隐式转换可以工作,但以下操作将失败:
List<Fruit> f = new List<Apple>();
List f=新列表();
List
和List
是完全不同的类别。它们之间没有直接的转换,无论是隐式的还是显式的。你在搜索什么,叫做什么。在你的例子中-泛型中的协方差。根据规定,它仅适用于有限的一组类型:
这很好:
IEnumerable<Derived> b = new List<Derived>();
IEnumerable<Base> a = b;
IEnumerable b=新列表();
i可数a=b;
这不起作用:
IList<Derived> b = new List<Derived>();
IList<Base> a = b;
IList b=新列表();
IList a=b;
因此,在您的例子中,FooRef
是直接从BaseReference
派生的,因此可以将其转换为这种类型,而c#不能简单地将BaseReference
转换为BaseReference
,因为通用参数协方差存在问题
可能会有一些解决办法,分离的方法通过硬编码从一种类型转换到另一种类型,但是,我想,应该完全避免这种行为。当然,这是因为Foo是带有附加项的BaseObjectWithID,fooRef使用Foo,BaseObjWithId是一个较小的版本,它不是相同的,因为它没有意义,你正在尝试做什么。虽然可以强制转换它,但它没有任何用途。因为
FooRef
绑定到具体类Foo
的实例,所以除非您将FooRef设置为太泛型,否则无法将其绑定到其基类,这不是关于类型转换,而是关于泛型,因为Foo
继承自BaseObjWithId
,这并不意味着BaseReference
继承自BaseReference
,不是-它们是两种不同的类型。Cage
是一个可以容纳任何动物的笼子。水族馆
是一个笼子
。所以你能在你需要水族馆的地方用一个笼子吗?不水族馆保证只有鱼出来,但笼子可以释放老虎。你能在需要笼子的地方使用水族馆吗?不可以。你可以把长颈鹿放进笼子
,但不能放进水族馆
。由于无法在两个方向上进行转换,因此水族馆
和笼子
之间必须没有类型关系。