C#中引用类型的隐式/显式转换是否改变实际类型?
C#引用类型与值类型转换的实际类型差异解析
核心结论
引用类型的转换不会改变堆上对象本身的实际类型,只是修改了栈上引用变量的类型;而值类型的转换会生成新的实例,因此实际类型会发生变化。
一、引用类型转换的本质
C#中引用类型的对象实例存储在托管堆上,变量本身只是栈上的一个"指针"(引用),指向堆上的对象。当你进行继承关系下的引用转换(比如Teacher转Person)时:
- 只是改变了引用变量的类型,让它只能访问父类
Person的成员,但堆上的对象本身完全没变,还是Teacher类型。 - 不管是隐式向上转换(
Teacher→Person)还是显式向下转换(Person→Teacher),都是操作引用变量的类型,对象本身的类型始终由new关键字创建时决定。
看你的测试代码:
Person teacherToPerson = teacher;:teacherToPerson是Person类型的引用,但指向的依然是堆上的Teacher实例,所以GetType()返回Teacher。Teacher TtoPtoT = (Teacher)teacherToPerson;:只是把引用重新转成Teacher类型,对象还是原来的那个,类型自然不变。Person p844 = new Teacher(30);:p844是Person引用,但实际创建的是Teacher对象,GetType()必然返回Teacher。
二、值类型转换的本质
值类型(比如float、double、int)的实例直接存储在栈上(或作为结构体成员存储)。当进行值类型转换时,会基于原数值创建一个新的实例,并转换为目标类型:
- 比如
float floatNum = 4.5f; double dNum = floatNum;,这里是把floatNum的数值复制后,转换成double类型的新值存储到dNum中,dNum本身就是double类型的实例,所以GetType()返回double。
容易遗漏的点
如果自定义了类型转换运算符(用implicit或explicit关键字),引用类型转换也可能生成新对象,改变实际类型。比如:
class Teacher : Person { // 自定义显式转换:Teacher转Person时生成新的Person对象 public static explicit operator Person(Teacher t) { return new Person(t.Age); } }
这时执行Person p = (Person)teacher;,p.GetType()会返回Person,因为转换生成了新的Person实例。但默认的继承关系转换是引用转换,不会创建新对象,所以实际类型不变。
内容的提问来源于stack exchange,提问作者JejuOrange
相关产品推荐
相关产品推荐

