C# 将派生类的实例赋值给基类的变量

C# 将派生类的实例赋值给基类的变量,c#,.net,C#,.net,您好,我是C#的新手,我正在尝试解决“隐式转换”操作。我有一个问题: class Animal { } class Monkey : Animal { } Monkey m = new Monkey(); Animal a = m; m.GetType() [Submission#165+Monkey] a.GetType() [Submission#165+Monkey] 猴子m2=a;//这将调用-编译器错误CS0266。

您好,我是C#的新手,我正在尝试解决“隐式转换”操作。我有一个问题:

    class Animal { }
    class Monkey : Animal { }

    Monkey m = new Monkey();
    Animal a = m; 
    m.GetType()
    [Submission#165+Monkey]
    a.GetType()
    [Submission#165+Monkey]
猴子m2=a;//这将调用-编译器错误CS0266。 无法将类型“Animal”隐式转换为“Monkey”。明确的

存在转换(您是否缺少演员阵容?)

我不明白——若最后一行代码抛出错误CS0266,为什么GetType方法返回“a”变量的类型为“Monkey”。如果“a”变量是动物,如何找到它?用什么方法

GetType()
在运行时进行计算。您得到的错误是在编译时,也就是在程序运行之前

编译器需要使用它在编译时拥有的信息来确保类型安全。确保意味着确保不会出错。将
动物
分配给
猴子
通常是不安全的,因为
老虎
也是一种动物,因此理论上可以将老虎分配给猴子类型的变量

您可以告诉编译器,虽然赋值不安全,但您知道自己在做什么。您可以通过显式强制转换执行此操作:

在这里你告诉编译器;“嘿,我知道这通常不安全,但相信我,我知道
a
Monkey

编译器将接受您的承诺,但不会完全信任您,因此将在运行时执行类型检查以确保,如果您的承诺是谎言,您将得到运行时错误。

GetType()
在运行时进行计算。您得到的错误是在编译时,也就是在程序运行之前

编译器需要使用它在编译时拥有的信息来确保类型安全。确保意味着确保不会出错。将
动物
分配给
猴子
通常是不安全的,因为
老虎
也是一种动物,因此理论上可以将老虎分配给猴子类型的变量

您可以告诉编译器,虽然赋值不安全,但您知道自己在做什么。您可以通过显式强制转换执行此操作:

在这里你告诉编译器;“嘿,我知道这通常不安全,但相信我,我知道
a
Monkey


编译器将接受您的承诺,但不会完全信任您,因此将在运行时执行类型检查以确保,如果您的承诺是谎言,您将得到一个运行时错误。

变量的类型是
Animal
,编译器不允许您将其分配给
猴子
,因为
动物
不一定是
猴子
。您可以反过来分配,因为
猴子
始终是
动物
GetType()
返回编译器不知道、也不可能知道的变量所指向的对象的运行时类型

变量的类型为
Animal
,编译器不允许您将其分配给
Monkey
,因为
Animal
不一定是
Monkey
。您可以反过来分配,因为
猴子
始终是
动物
GetType()
返回编译器不知道、也不可能知道的变量所指向的对象的运行时类型

从父类到子类的重复播放:从父类到子类的重复播放:中间,谢谢您的回复!无论如何,我还有一个问题:当我不理解时,编译器从上到下读取脚本。当它读取最后一行代码时,它只能知道“a”变量被声明为Animal,因为代码还没有运行,所以它不知道“a是Monkey”,这就是它抛出异常的原因。我说的对吗?@UIxH不必担心顺序,一般来说,这不相关。编译器看到的是一个变量
a
typed
Animal
,它被正确地初始化为某个对象。某些东西(一个
Monkey
)只能在运行时知道(它不是编译时常量),编译器不能再对它进行任何推理,除非赋值是安全的。另外,不要将编译时错误与异常混淆。异常发生在运行时,您将得到一个编译时错误,这些错误发生在编译时。@UIxH:“自上而下”参数对编译器的要求过高。编译器不会仅仅为了验证一行代码而评估整个程序。它基于一些预定义的检查(类型匹配吗?所有提到的变量都存在吗?这些方法/属性可访问吗?)验证一行。尽管其中一些检查包括查看一行代码以外的内容(例如,检查变量是否都存在),但类型不匹配的检查只针对行本身进行,而不查看前面的代码。@在这两者之间,这是数字,感谢您为我澄清这一点。我没有注意到EXCEPTIONS和编译时错误之间的区别,现在我会的。@flatterthak you,编译器的工作变得更清楚了。在这两者之间,谢谢你的回复!无论如何,我还有一个问题:当我不理解时,编译器从上到下读取脚本。当它读取最后一行代码时,它只能知道“a”变量被声明为Animal,因为代码还没有运行,所以它不知道“a是Monkey”,这就是它抛出异常的原因。我说的对吗?@UIxH不必担心顺序,一般来说,这不相关。编译器看到的是一个变量
a
typed
Animal
,它被正确地初始化为某个对象。某些东西(一个
Monkey
)只能在运行时知道(它不是编译时常量),编译器不能再对它进行任何推理,除非赋值是安全的。另外,不要将编译时错误与异常混淆。例外情况发生在ru
Monkey m2 = (Monkey)a;