Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解C#和#x27;s型转换_C# - Fatal编程技术网

理解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
是一个可以容纳任何动物的笼子。
水族馆
是一个
笼子
。所以你能在你需要水族馆的地方用一个笼子吗?不水族馆保证只有鱼出来,但笼子可以释放老虎。你能在需要笼子的地方使用水族馆吗?不可以。你可以把长颈鹿放进
笼子
,但不能放进
水族馆
。由于无法在两个方向上进行转换,因此
水族馆
笼子
之间必须没有类型关系。