日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系

發布時間:2024/4/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CLR要求對象必須使用new運算符創建,在使用new運算符創建一個對象時具體都做了些什么呢?

1.計算所有定義的實例字段,所有的基類型包括System.Object需要分配的字節數。

每一個堆上的對象還需要兩個額外的成員:類型對象指針 和同步塊索引,CLR使用它們來管理對象。它們兩個需要的字節數算在對象的大小里面。

2.從托管堆分配對象需要的字節數(也就是給對象分配內存)。所有的字節置為0

3.初始化類型對象指針 和同步塊索引

4.調用實例構造器。大多數編譯器自動生成調用基類構造器的代碼。最終會調用Sytem.Object的構造器,這個構造器方法什么也不做,只是return。

在new執行完上面的操作以后,返回一個新創建的對象的引用,這個引用保存在實例對象變量里。如:A a=new A();?? 保存在變量a里。

?

is和as運算符

//o是一個Object對象 Employee是一個類 if(o is Employee) {Employee e=(Employee)o;... }

上面的代碼是關于is非常典型的應用,這里CLR會進行兩次類型 檢查:①is運算符檢查 ? ②執行強轉的時候檢查。CLR的類型檢查提高了安全性,同時也會消耗一部分性能。C#提供了as運算符來簡化代碼并且改善性能。

Employee e=o as Employee; if(e!=null) {//... }

這里CLR會檢查o的類型是否兼容Employee,如果兼容則返回Employee對象的引用,否則返回null。這里只執行了一次類型檢查。

?

運行時類型,對象,線程堆棧,托管堆之間的聯系

當創建一個線程時,會分配1M的堆棧空間,用來向方法傳遞參數以及存放定義在方法里面的局部變量。堆棧的建造是從高位內存地址向地位內存地址進行。下面演示一個線程執行調用M1方法的過程:

M1方法執行時,首先會在堆棧上為name變量分配內存:

接著M1調用M2方法,將name局部變量作為參數參數傳遞,name變量的地址進棧:

接著會執行M2方法,首先還是給length和tally兩個局部變量從堆棧上分配內存:

M2執行到return語句,返回到M1,繼續執行。

?

調用靜態方法,實例方法以及虛方法之間的不同

internal class Employee { public Int32 GetYearsEmployed() { ... } public virtual String GetProgressReport() { ... } public static Employee Lookup(String name) { ... } } internal sealed class Manager : Employee { public override String GetProgressReport() { ... } }

加入代碼接著調用M3方法,M3方法包含的代碼闡釋了CLR的運行原理(一般可能不這樣寫代碼)

上圖展示CLR載入到進程,托管堆初始化。

當JIT編譯器將M3的IL代碼編譯為本地CPU指令時,CLR會保證定義這些類型的程序集加載。使用程序集的元數據,CLR這些類型的信息并創建一些數據結構來呈現類型本身。關于Employee和Manager類型展示如下:


(Int32和String是常用的類型,這里沒有展示)

1.在定義一個類型時,可以定義一個靜態數據字段,存放類型對象本身的內存分配的字節數。每一個類型對象里面是一個包含每個方法入口的方法表,這里的Employee定義了GetYearsEmployed , GetProgressReport, 和Lookup三個方法,所以在Employee的方法表里面有三個入口。在CLR確定了所有的方法被創建并編譯之后,線程開始執行M3的CPU指令。同樣,這里會為M3方法的局部變量分配內存,(初值為0或null)。

2.接著M3執行構造器創建Manager對象,

3.接著執行下面的代碼,M3調用靜態方法Lookup。當調用靜態方法時,JIT編譯器會定位到跟定義靜態方法相對應的類型對象。然后,JIT編譯器定位到方法表的入口處。Lookup方法在堆上構造了一個Manager對象并且返回該對象的地址。保存在變量e中,此時e不再指向開始new出來的那個Manager對象,開始的Manager對象已經沒有變量引用它。在未來某個時候GC會對它進行回收。

4.接著M3調用非虛方法的實例方法GetYearsEmployed,CLR會定位到與變量e類型一致的對象。(如果Employee沒有定義該方法,JIT編譯器會向上一層層查找直到Object。

然后JIT編譯器定位到對象的方法表,這里可以看出相對于靜態方法多了一步定位。編譯該方法(如果之前沒有編譯過),調用編譯后的代碼。

5.接著M3調用虛方法實例方法GetProgressReport,調用時,JIT會生成一些額外的代碼,這些代碼在每一次方法調用時都會執行,它會首先會查找發起調用的變量,然后跟隨地址來調用對象。這里的e變量執行了Manager對象,生成的額外的代碼會檢查對象內部的類型對象指針,該指針成員引用了實際的對象的類型。然后定位到對象的方法表,接著編譯。

?

?

注?? 《CLR via C#》(Jeffrey Richter著)——.NET 界的經典之作,讀的過程寫點筆記跟大家分享,我也推薦大家看英文版,能夠直接領會原意 ?

轉載于:https://www.cnblogs.com/mszhangxuefei/archive/2012/07/24/clrnotes-4.html

總結

以上是生活随笔為你收集整理的new,is和as运算符解析及运行时类型,对象,线程堆栈,托管堆之间的联系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。