【问题标题】:Assigning instance of a derived class to a variable of base class将派生类的实例分配给基类的变量
【发布时间】:2017-12-08 10:40:07
【问题描述】:

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

    class Animal { }
    class Monkey : Animal { }

    Monkey m = new Monkey();
    Animal a = m; 
    m.GetType()
    [Submission#165+Monkey]
    a.GetType()
    [Submission#165+Monkey]

Monkey m2 = a;// 此调用 - 编译器错误 CS0266。 无法将类型“动物”隐式转换为“猴子”。明确的

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

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

【问题讨论】:

标签: c# .net


【解决方案1】:

GetType() 在运行时进行评估。您得到的错误发生在 compile 时间,即在程序运行之前。

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

您可以告诉编译器,尽管赋值不安全,但您知道自己在做什么。您可以通过 explicit 演员来做到这一点:

Monkey m2 = (Monkey)a;

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

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

【讨论】:

  • InBetween,谢谢您的回复!无论如何我还有一个问题:因为我不明白编译器从上到下读取脚本。当它读取最后一行代码时,它只能知道 "a" 变量被声明为 Animal 并且因为代码还没有运行它不知道 "a is Monkey" ,这就是它抛出异常的原因。我说的对吗?
  • @UIxH 不用担心顺序,一般来说它是不相关的。编译器看到的是一个变量a,类型为Animal,它被正确初始化为something。那个东西(Monkey)只能在运行时知道(它不是编译时间常数),编译器无法推断出更多关于它的东西,除了赋值是安全的。此外,不要将编译时错误与异常混淆。异常发生在运行时,你得到一个编译时错误,这些发生在编译时。
  • @UIxH:“从上到下”参数对编译器的期望过高。编译器不会评估整个程序只是为了验证您的一行代码。它基于一些预定义的检查来验证一行(类型是否匹配?是否所有提到的变量都存在?这些方法/属性是否可访问?)。尽管其中一些检查包括查看比一行代码更远的内容(例如检查变量是否全部存在),但类型不匹配的检查仅针对该行本身进行,而不看前面的代码。
  • @InBetween,这个数字,谢谢你让我明白。我没有注意异常和编译时错误之间的区别,现在我会的。
  • @Flater thak you,编译器的工作变得更清楚了。
【解决方案2】:

变量的类型是Animal,编译器不允许您将其分配给Monkey,因为Animal 不一定是Monkey。你可以反过来分配,因为Monkey总是AnimalGetType() 返回变量指向的对象的运行时类型,编译器不知道也不知道任何事情。

【讨论】:

  • 感谢您的回答,这扩展了!无论如何,我还有一个问题:因为我不明白编译器会从上到下读取脚本。当它读取最后一行代码时,它只能知道 "a" 变量被声明为 Animal 并且因为代码还没有运行它不知道 "a is Monkey" ,这就是它抛出异常的原因。我说的对吗?
猜你喜欢
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
  • 2020-03-24
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
相关资源
最近更新 更多