C#如何识别引用的真实类型(一)——转载

知识储备,如果您已经十分熟习这些,可以跳过

1 什么是引用?

 引用是一个数据结构,包含了一个计算机内存堆地址的值,就类似C++中的指针一样,本文中所有出现有关"引用"字句,读者都可以把它理解成C,C++中的指针

  再说一遍,引用 与 指针 是不同的,例如 GC在回收内存的时候,会修改引用的值,但本文的重点并不是讲述 引用 与 指针的差别,所以,读者可以把所有在这里出现的 "引用" 理解成 c,c++ 中的指针

2 栈 与 堆, .net中的内存分配?

  http://blog.csdn.net/cuike519/archive/2009/12/23/5063333.aspx ,如果你还不是很清楚这些,这里有你所需要了解的

方法是类的,非静态字段是实例的

  类中的方法(无论是静态的,还是非静态的)本质上都是属于类的,类中非静态的字段,是属于类的实例的

  正是因为这一点的不同,类中的方法代码只创建了一份在内存中,而类中的非静态字段是随着类的实例创建而创建的

  理论上 ,实例一个类的对象,只需要在内存中分配 与 类中所有非静态字段总和大小 一致的内存就可以了

  然后把分配的堆中内存地址的首地址 赋给 栈 中的引用

  但,实际情况并非如此简单,在.net 中,当实例化一个类的时候, 总共分配了( sizeof(void*) + 类中所有非静态字段大小总和 )  的内存

  那么,那多出的 sizeof(void*) 是用来做什么的呢?

P.S.  如果我没有记错的话 在32位的CPU下, sizeof(void*) 的大小是4个字节

那多出来的4字节,是做什么的呢?

 引用指向了一个内存地址,在该地址 + sizeof(void*) 后便紧跟着实例的非静态字段

 每个类都拥有 sizeof(void*) 大小的"多余"内存,那么在那里面,究竟有什么呢?

 在那里面,总共有两个东西

 第一个是名为 syncblock 的索引

 第二个是指向一个为公开的数据结构的句柄

 不要小看那个未公开的数据结构,那里有实际类型的相关数据,.net正是依靠它来准确识别引用的真实类型,就算你按照以下的例子做,CLR也会知道,谁到底是谁

  Subclass sub = new Subclass();

  BassClass B = (BassClass)sub;

  B.GetType(); // CLR说,别装B了,我知道你是 subclass 类的实例

真像已经大白,还想要知道更多?

  

   1, 那个未公开的数据结构,有一个名字,叫做 CORINFO_CLASS_STRUCT(这个名字只是做参考,实际中,也许并不是这个名字),我们无法使用编程的方法直接访问这个数据结构,但是.net提供了一个类, System.RuntimeTypeHandle 允许我们用已经定义好的方法,访问它

  有关 System.RuntimeTypeHandle 的更多信息,请参照MSDN

   

   2, MSIL提供了两个进行类型间相互转换的IL指令

    isinst

    castclass

    这两个指令在编译成本机代码的时候,都会产生访问 CORINFO_CLASS_STRUCT以验证是否可以进行转换

    它们唯一的不同是当验证失败时,castclass 抛出一个 System.InvalidCastException异常 (很熟习吧?)

    isint 则会将一个为 null 的引用添加到栈顶 (MSIL是一门基于栈的语言,有兴趣的童鞋,可以google下 :-))

    在C#中

    as ,is 操作符 被转换成 isinst

   

     () 强制类型转换符 被转换成     castclass

原文发布时间为:2010-03-19

时间: 2024-10-24 16:44:44

C#如何识别引用的真实类型(一)——转载的相关文章

as 3.0引用与值类型区别

上节讲了数据类型现在我们来讲讲as 3.0引用与值类型区别哦,引用在编程中经常用到,并用很有好处,至少什么好处各位可以自己想一下吧我也不说了我们现比较一下引用与值类型区别哦. 值类型:    是直接去访问变量的地址 引用:   就是引用一个变量的地址,值会因一个变量的改变而改变 下面来看个例子吧. var an:int =3; var bn:int =an; bn =65555; trace('an值是'+an); trace('an值是'+bn); 输出结果的值为: an =3 ;bn =65

引用类型必须与其引用对象的类型一致的第二个例外是什么?

问题描述 引用类型必须与其引用对象的类型一致的第二个例外是什么? <C++ Primer>第五版,中文版.p55. 好像只有一种.56 页又提到了一次两个例外,但是用的还是第一种. 解决方案 不一定一致,可以是派生类型,还有一个例外应该说的是模板类型. 解决方案二: 对象引用类型 解决方案三: 在 534 页.46 页提到了.

python改变引用对象的类型,为什么最后打印出来的饮用计数会很大 ?

问题描述 python改变引用对象的类型,为什么最后打印出来的饮用计数会很大 ? 例:a = [5] print (getrefcount(a)) a = 7 print(getrefcount(a)) 解决方案 求 ....大神来解答

CLR笔记:5.基元,引用和值类型

5.1基元类型 编译器(C#)直接支持的任何数据类型都称为基元类型(primitive type),基元类型直接映射到FCL中存 在的类型.可以认为 using string = System.String;自动产生. FCL中的类型在C#中都有相应的基元类型,但是在CLS中不一定有,如Sbyte,UInt16等等. C#允许在"安全"的时候隐式转型--不会发生数据丢失,Int32可以转为Int64,但是反过来要显示 转换,显示转换时C#对结果进行截断处理. unchecked和che

生物识别对数字化生存的意义(转载)

问题描述 尼葛络庞帝在其震撼作<数字化生存>一书中为人们展现了信息时代数字化生活的全景.从数字办公到数字家庭,再到数字娱乐,从虚拟现实到信息时代的人性化世界,都作出了雄宏的勾勒.其中着墨最多的当属人机界面.尼葛络庞帝在书中预言"信息业会变得象服装业.但这个只有当我们改进了人和电脑之间的界面,使得人与电脑的对话像人与人对话一样容易才会出现."当前GUI的界面相比曾经的字符时代,发生了质的飞跃,但相对数字化生活来讲,目前的人机交互的界面对人们仍然是够"辛苦"

PHP取二进制文件头快速判断文件类型的实现代码_php技巧

一般我们都是按照文件扩展名来判断文件类型,但是这个很不靠谱,轻易就通过修改扩展名来躲避了,一般必须要读取文件信息来识别,PHP扩展中提供了类似 exif_imagetype 这样的函数读取图片类的文件类型,但是很多时候扩展不一定安装了,有时候就需要自己来实现识别文件类型的工作. 下面代码就展示了自己通过读取文件头信息来识别文件的真实类型. 复制代码 代码如下: <?php     $files = array(        'c:\1.jpg',        'c:\1.png',     

Java基础教程之类型转换与多态_java

我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程.我将在这一讲中深入类型,并介绍多态(polymorphism)的概念.  类型检查 Java的任意变量和引用经过类型声明(type declaration),才能使用.我们之前见过对象数据.类数据.方法参数.方法返回值以及方法内部的自动变量,它们都需要声明其类型.Java是一种强类型(strongly typing)语言,它会对类型进行检查.如果我们错误的使用类型,将造成错误.  类型不符,卖萌无效  比如在下面的Test

Java基础12 类型转换与多态

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!   我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程.我将在这一讲中深入类型,并介绍多态(polymorphism)的概念.   类型检查 Java的任意变量和引用经过类型声明(type declaration),才能使用.我们之前见过对象数据.类数据.方法参数.方法返回值以及方法内部的自动变量,它们都需要声明其类型.Java是一种强类型(strongly

vb变量、常数和数据类型及过程概述(五)

Object 数据类型Object 变量作为 32 位(4 个字节)地址来存储,该地址可引用应用程序中或某些其它应用程序中的对象.可以随后(用 Set 语句)指定一个被声明为 Object 的变量去引用应用程序所识别的任何实际对象.Dim objDb As ObjectSet objDb = OpenDatabase ("c:\Vb5\Biblio.mdb")在声明对象变量时,请试用特定的类,而不用一般的 Object(例如用 TextBox而不用 Control,或者像上面的例子那样