指定基类的类型时,C#类型转换返回子类
本文关键字:类型转换 返回 子类 基类 类型 | 更新日期: 2023-09-27 18:29:22
当我运行以下程序时:
ParentClass foo = serializer.Deserialize(xmlReader) as ParentClass;
xmlReader
中加载的xml文档是ParentClass
的继承类型。在调试器中检查时,foo
显示为继承类的实例,而不是父类。当然,继承的类也是ParentClass类型,但是为什么as
关键字会有这种行为呢?为什么C#不去掉所有其他不需要转换为ParentClass
的对象信息。
这不是一个问题,但或多或少是一个出于好奇的问题。
对象本身没有被修改,这就是为什么对象的类型在调试器中仍然显示为"ParentClass"的原因。
考虑下面的例子,我认为这是说明性的。你认为这里控制台的输出是什么?
class Program
{
public class ParentClass
{
public virtual void foo()
{
Console.WriteLine("parent.foo");
}
public virtual void bar()
{
Console.WriteLine("parent.bar");
}
}
public class InheritedClass : ParentClass
{
public new void foo()
{
Console.WriteLine("inherited.foo");
}
public override void bar()
{
Console.WriteLine("inherited.bar");
}
}
static void Main(string[] args)
{
var inherited = new InheritedClass();
var parent = inherited as ParentClass;
var d = parent as dynamic;
parent.foo();
inherited.foo();
d.foo();
parent.bar();
inherited.bar();
d.bar();
Console.Read();
}
}
只创建一个对象,然后再创建两个对它的引用:一个是继承的静态类型,另一个是"动态"类型。调用"bar"调用"InheritedClass.bar"而不考虑静态类型(运行时类型始终相同),这一事实证明了所有引用都引用了同一对象。
但是,请注意使用"override"answers"new"之间的区别:您将看到"parent.foo()"调用"ParentClass.foo"方法。这是因为"parent"变量属于静态类型"ParentClass"类型,因此C#编译器会发出IL指令来调用"ParentClass"上的方法。您可以进一步看到,"dynamic"类型引用仍然调用"InheritedClass.foo",因为动态类型在运行时解析,并且这解析为实际的运行时类型"Inherited Class"。
编辑@InBetween有一个我没有考虑到的重要区别。在从值类型强制转换为引用类型的情况下(反之亦然),实际创建了一个新对象,因为必须分别在堆或堆栈上分配新内存("装箱"过程)。当然,部分原因是struct
和其他值类型不支持虚拟方法。
as
只能执行引用转换、可为null的转换和装箱转换。它不会执行任何其他类型的转换,如用户定义的转换。
在您的情况下,它执行兼容的引用转换;对象保持不变,您只是在更改引用。
但是as
可以"修改"一个对象,我想你是在说,例如,装箱不仅仅需要转换引用。
var o = 1 as object;
CCD_ 10是与整数CCD_ 11完全不同的对象。
值得注意的是,在任何成功的as
转换中,GetType()
仍将返回对象的原始类型,而不是强制转换运算符的一般行为。