8

我有一个基类和一个派生类,如下所示

public class animal
{
    public string name { get; set; }
}

public class dog : animal
{
    public int age { get; set; }
    public string type { get; set; }
}

用途:

animal a = new animal();

dog d = new dog();

a = d; //compiled

d = a; //Error:Cannot implicitly convert type 'animal' to 'dog'.

d = (dog)a; // compiled

派生类可以分配给基类但需要进行反向显式转换的内部发生了什么?即使基类和派生类都包含相同的成员,也发现相同的结果。

4

5 回答 5

9

所有的狗都是动物,但并非所有的动物都是狗。不允许隐式转换,因为您的 a 可能实际上不是 d。

于 2011-12-16T03:09:50.253 回答
6

当您使用显式转换时,在您的情况下,您是在告诉编译器您知道发生了什么。如果您要编译代码,删除d = a;,并且您尝试访问 上的公共成员d,则会引发异常。这是因为,在这种情况下,animal不是dog. 您显式创建了一个animal并将其分配给a.

当您知道转换将起作用时,显式转换允许您执行操作。

public class MyClass
{
    public animal MyAnimal { get; private set; }

    public MyClass ()
    {
        MyAnimal = new dog ();
    }

    public void SetAge (int Age)
    {
        ((dog)MyAnimal).age = Age;
    }
}

在这种情况下,我们知道它MyAnimal实际上是 a dog,因此我们可以对其进行显式转换。由于继承,所有这些都有效。因为继承不能双向工作,所以编译器不允许隐式向上转换——你必须显式地进行。

我们知道,当一个类从其基类继承时,它带有公共属性和方法。你不能说你对 an 的引用animal总是包含 a 的属性和方法dog

于 2011-12-16T03:18:08.853 回答
3

它是一个简单的继承规则。例如:Dog 是 Animal但 reverse 不是 true - Animal is Dog。可能有许多动物的子类。

class Animal {}
class Dog : Animal {}
class Cat : Animal {}

Animal a=new Cat(); // OK
a=new Dog(); // OK

Cat c=a; //Invalid - var a might contains reference of Cat or Dog
Cat d=(Cat)a; // Throws InvalidCastException exception because "a" has ref. of Dog

因此,超类引用变量可以在不强制转换的情况下保存子类对象的引用,但是当您将超类引用变量的引用分配给子类引用变量时,您必须进行强制转换。

查看 MSDN 文章 - How to: Safely Cast by Using as and is Operators (C# Programming Guide)。

于 2011-12-16T03:11:58.480 回答
2

这样想,所有的狗都已经是动物,但并非所有的动物都是狗。要将动物分配给狗,您必须首先将其转换为狗。

于 2011-12-16T03:09:39.243 回答
2

派生类可以分配给基类但需要进行反向显式转换的内部发生了什么?即使基类和派生类都包含相同的成员,也发现相同的结果。

无论哪种情况,内部几乎都没有发生任何事情。对象未被修改或复制;相反,只是对它的引用存储在具有不同类型的新变量中。

dog允许从to 进行隐式转换,animal因为如果dog变量可以保存对对象的引用,则对象必须是 adog或 apoodle或诸如此类,因此animal变量也可以保存对它的引用。

相比之下,需要从animalto显式转换,dog因为该animal对象实际上可能不是 a dog,在这种情况下,运行时系统将引发异常。(还记得我说过“内部几乎什么都没有发生”吗?这是“几乎没有”,因为运行时系统必须检查以确保对象是 a dog,否则会引发异常。)

This is a language design decision — we could definitely create a language that's exactly like C#, except that dog d = a; is equivalent to dog d = (dog) a;, but the designers of C# (and many similar languages) felt that it would be confusing for dog d = a; to raise a run-time exception sometimes. The explicit cast makes clear that an exception is possible unless a refers to a dog.

于 2011-12-16T03:23:33.760 回答