当我运行以下内容时:
ParentClass foo = serializer.Deserialize(xmlReader) as ParentClass;
xmlReader
中加载的xml文档是ParentClass
的继承类型。在调试器中检查时,foo
显示为继承类的实例,而不是父类。当然,继承的类也是ParentClass类型,但为什么as
关键字有这种行为?为什么C#不会删除转换为ParentClass
所不需要的所有其他对象信息。
这不是问题,但或多或少是出于好奇的问题。
答案 0 :(得分:1)
对象本身未被修改,这就是为什么对象的类型仍然在调试器中显示为“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”和“new”之间的区别:您将看到“parent.foo()”调用“ParentClass.foo”方法。这是因为“父”变量属于静态类型“ParentClass”类型,因此C#编译器发出IL指令以在“ParentClass”上调用该方法。您可以进一步看到“动态”类型引用仍然调用“InheritedClass.foo”,因为动态类型在运行时解析,并且这解析为实际的运行时类型“InheritedClass”。
编辑 @InBetween有一个我没有考虑的重要区别。在从值类型转换为引用类型(反之亦然)的情况下,实际创建了一个新对象 ,因为必须分别在堆或堆栈上分配新内存(“装箱”)处理)。当然,部分由于这个原因,struct
和其他值类型不支持虚拟方法。
答案 1 :(得分:1)
as
只能执行引用转换,可空转换和装箱转换。它不会执行任何其他类型的转换,例如用户定义的转换。
在您的情况下,它执行兼容的参考转换;对象保持不变,您只是更改引用。
但as
可以"修改"一个对象,我认为你在说,例如,拳击不仅仅需要转换引用。
var o = 1 as object;
o
是一个与整数1
完全不同的对象。
重要的是要注意,在任何成功的as
转换中GetType()
仍然会返回不 的一般行为的对象的原始类型>演员。