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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

IL语言之.ctor

發(fā)布時(shí)間:2025/3/14 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IL语言之.ctor 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)述:構(gòu)造函數(shù),在類被實(shí)例化時(shí),它會(huì)被自動(dòng)調(diào)用。

當(dāng)C#的類被編譯后,在IL代碼中會(huì)出現(xiàn)一個(gè)名為.ctor的方法,它就是我們的構(gòu)造函數(shù),對(duì)應(yīng)C#中的構(gòu)造函數(shù)。且看下面的代碼:

public class Class1
{
????
private string name;
????
private int age;
}


類Class1中沒(méi)有顯示的構(gòu)造函數(shù),只有兩字段,現(xiàn)在用ILDasm.exe打開(kāi)編譯后生成的exe文件,會(huì)看到:



可以看到這里有個(gè).ctor,我們沒(méi)有定義構(gòu)造函數(shù),但這里卻出現(xiàn)了.ctor,這就說(shuō)明了:

當(dāng)沒(méi)有顯示定義構(gòu)造函數(shù)時(shí),會(huì)自動(dòng)生成一個(gè)構(gòu)造函數(shù),它沒(méi)有參數(shù),沒(méi)有返回值。

那我們來(lái)看看這個(gè).ctor都干了什么吧,雙擊.ctor打開(kāi),在彈出的窗口中可以找到下面的幾行代碼:

IL_0000: ldarg.0

IL_0001: call?????? instance void [mscorlib]System.Object::.ctor()

IL_0006: ret

上面就是這個(gè).ctor的方法體,看上面的紅色行,從字面上可以看出,它是調(diào)用(call)了一個(gè)類型為System.Object的實(shí)例的.ctor()方法,從這就可以證明:

當(dāng)一個(gè)類沒(méi)有顯示聲明繼承于其它某個(gè)類時(shí),它將默認(rèn)繼承自System.Object,并且,在類的構(gòu)造函數(shù)中將會(huì)調(diào)用其基類的構(gòu)造方法(.ctor)。

現(xiàn)在對(duì)上面的程序小改一下,在聲明name時(shí)對(duì)其初始化:

public class Class1
{
???
private string name = "Lin";
???
private int age;
}

再用ILDasm打開(kāi)生成的exe文件,打開(kāi).ctor,里面有這么幾行:

??IL_0000: ldarg.0

IL_0001: ldstr????? "Lin"

IL_0006: stfld????? string ConsoleApplication1.Class1::name

IL_000b: ldarg.0

IL_000c: call?????? instance void [mscorlib]System.Object::.ctor()

IL_0011: nop

這個(gè)跟剛才的相比,多出了紅色的那兩行,這兩行出現(xiàn)在“調(diào)用System.Object的構(gòu)造方法”之前,這說(shuō)明:

如果在字段聲明的同時(shí)對(duì)其初始化,那么在編譯后,賦值過(guò)程將被放到構(gòu)造方法.ctor中,并且在調(diào)用其基類的構(gòu)造方法之前進(jìn)行。

現(xiàn)在給上面的C#程序顯式加上一個(gè)構(gòu)造方法,它接受兩個(gè)參數(shù):

.cctor

簡(jiǎn)述:類型初始化器,是一個(gè)靜態(tài)方法,無(wú)參數(shù)無(wú)返回值,不能直接調(diào)用,最多只有一個(gè)

我們現(xiàn)在先給剛才的代碼加上一個(gè)靜態(tài)字段:
public class Class1
{
????????
private string name = "Lin";
????????
public static int count = 50;
????????
private int age;

????????
public Class1(string name, int age)
????????
{
????????????
this.name = name;
????????????
this.age = age;
???????? }

}


再來(lái)打開(kāi)ILDasm來(lái)看看:

發(fā)現(xiàn)這里多了一個(gè).cctor,它就是類型初始化器,打開(kāi)它,會(huì)看到其中有一句:

??IL_0000: ldc.i4.s?? 50

IL_0002: stsfld???? int32 ConsoleApplication1.Class1::count

它對(duì)靜態(tài)字段count進(jìn)行了賦值,值是50,那么,是.cctor先調(diào)用還是.ctor先調(diào)用呢?當(dāng)然是.cctor,它是為初始化類型而生的,專搞靜態(tài)的東東,而.ctor是構(gòu)造方法,當(dāng)然.cctor要先調(diào)用了。

現(xiàn)在顯示加上一個(gè).cctor,在C#中就是加個(gè)靜態(tài)構(gòu)造函數(shù),我們不能為其指定訪問(wèn)修飾符(否則編譯就會(huì)報(bào)錯(cuò)):

public class Class1
{
????????
private string name = "Lin";
????????
public static int count = 50;
????????
private int age;

????????
static Class1()
????????
{
???????????? count
= 100;
???????? }


????????
public Class1(string name, int age)
????????
{
????????????
this.name = name;
????????????
this.age = age;
???????? }

}

再來(lái)看看現(xiàn)在ILDasm下的.cctor,其中有幾行:

IL_0000: ldc.i4.s?? 50

IL_0002: stsfld???? int32 ConsoleApplication1.Class1::count

IL_0007: nop

IL_0008: ldc.i4.s?? 100

IL_000a: stsfld???? int32 ConsoleApplication1.Class1::count

可以看到:
如果在聲明靜態(tài)字段時(shí)同時(shí)對(duì)其賦值,它在編譯后會(huì)被搬到.cctor中,并且是放在前面,然后才到顯式定義的靜態(tài)構(gòu)造方法體中的代碼,也就是說(shuō)count在這里會(huì)被賦值兩次,第一次50,第二次100。

public class Class1
{
????????
private string name = "Lin";
????????
private int age;

????????
public Class1(string name, int age)
????????
{
????????????
this.name = name;
????????????
this.age = age;
???????? }

}

再用ILDasm打開(kāi)exe時(shí),會(huì)發(fā)現(xiàn)有了點(diǎn)變化:

這里的.ctor帶了兩參數(shù),一個(gè)string類型,一個(gè)int32類型,而剛才的無(wú)參無(wú)返回值的.ctor不見(jiàn)了,這也證明了:

如果類中有顯式定義構(gòu)造方法,那么就不會(huì)再自動(dòng)生成一個(gè)無(wú)參數(shù)無(wú)返回值的默認(rèn)構(gòu)造方法。

打開(kāi).ctor,會(huì)看到其中有這么幾行:

IL_0000: ldarg.0

IL_0001: ldstr????? "Lin"

IL_0006: stfld????? string ConsoleApplication1.Class1::name

IL_000b: ldarg.0

IL_000c: call?????? instance void [mscorlib]System.Object::.ctor()

IL_0011: nop

IL_0012: nop

IL_0013: ldarg.0

IL_0014: ldarg.1

IL_0015: stfld????? string ConsoleApplication1.Class1::name

IL_001a: ldarg.0

IL_001b: ldarg.2

IL_001c: stfld????? int32 ConsoleApplication1.Class1::age

IL_0021: nop

從上面紅色標(biāo)識(shí)的代碼的順序中,我們可以進(jìn)一步得到:

如果在聲明字段時(shí)同時(shí)對(duì)其賦值,那么這個(gè)賦值過(guò)程將在類型的構(gòu)造方法(.ctor)中最先執(zhí)行,然后再執(zhí)行其基類的構(gòu)造方法,最后才輪到我們顯示定義的構(gòu)造方法體中代碼。

?

在繼承中對(duì)象構(gòu)造過(guò)程

看下面這段程序:

????public class A
????
{
????????
public int x = 1;
????????
public A() { m1(); }
????????
public void m1() { }
???? }


????
public class B : A
????
{
????????
public int y = 2;
????????
public static string sb = "B";
????????
public B() { m2(); }
????????
public void m2() { }
???? }


????
public class C : B
????
{
????????
public int z = 3;
????????
public static string sc = "C";
????????
public C() { m3(); }
????????
public void m3() { }
???? }


編譯后用ILDasm打開(kāi)生成的exe文件:


可以看到三者都有一個(gè).ctor,B、C中有.cctor,而A沒(méi)有,打開(kāi)B,C的.cctor,可以看到它們都負(fù)責(zé)初始化自己的靜態(tài)字段,現(xiàn)在主要來(lái)看它們的.ctor。

先看類C的.ctor:

IL_0000:? ldarg.0
? IL_0001:? ldc.i4.3
? IL_0002:? stfld????? int32 CLRviaCSharp.Chapter5.ClassInherit.C::z
? IL_0007:? ldarg.0
? IL_0008:? call?????? instance void CLRviaCSharp.Chapter5.ClassInherit.B::.ctor()
? IL_000d:? nop
? IL_000e:? nop
? IL_000f:? ldarg.0
? IL_0010:? ldc.i4.5
? IL_0011:? stfld????? int32 CLRviaCSharp.Chapter5.ClassInherit.C::z
? IL_0016:? ldarg.0
? IL_0017:? call?????? instance void CLRviaCSharp.Chapter5.ClassInherit.C::m3()


可以看到:

在C被實(shí)例化時(shí),它最先初始化在聲明時(shí)同時(shí)賦值的字段(非靜態(tài)),此處是將3賦給z,然后它會(huì)調(diào)用其基類的.ctor(),然后再調(diào)用自己的構(gòu)造器內(nèi)部賦值語(yǔ)句及實(shí)例方法m3(),值得注意的是,在執(zhí)行顯式定義的構(gòu)造方法體中的代碼前,會(huì)先調(diào)用其基類的構(gòu)造方法(創(chuàng)建基類的實(shí)例)。

再來(lái)看類B的.ctor():

IL_0000:? ldarg.0
? IL_0001:? ldc.i4.2
? IL_0002:? stfld????? int32 CLRviaCSharp.Chapter5.ClassInherit.B::y
? IL_0007:? ldarg.0
? IL_0008:? call?????? instance void CLRviaCSharp.Chapter5.ClassInherit.A::.ctor()
? IL_000d:? nop
? IL_000e:? nop
? IL_000f:? ldarg.0
? IL_0010:? call?????? instance void CLRviaCSharp.Chapter5.ClassInherit.B::m2()


同樣,我們可以看到,在實(shí)例化B時(shí),它會(huì)先把2賦給自己的y,然后再調(diào)用基類A的構(gòu)造方法,最后再調(diào)用自己的實(shí)例方法m2()。


那A的.ctor()就不再看了,可以猜到它一定是在做這樣的事:
1、 將1賦給實(shí)例的x字段;
2、 調(diào)用基類System.Object的構(gòu)造方法.ctor來(lái)創(chuàng)建基類的實(shí)例;
3、 調(diào)用實(shí)例方法m1();

總結(jié)

1、.ctor是構(gòu)造方法;
2、.cctor是類型初始化器,在C#中也就是靜態(tài)構(gòu)造函數(shù);
3、當(dāng)類C實(shí)例化時(shí),會(huì)先對(duì)聲明時(shí)就進(jìn)行賦值的字段賦值,然后調(diào)用基類的構(gòu)造函數(shù),基類再以同樣的方法構(gòu)造自己,一直到頂層的System.Object,然后再回來(lái)執(zhí)行C的顯式構(gòu)造方法中的代碼,就是這么一個(gè)遞歸的過(guò)程。

?

原文URL:http://hi.baidu.com/0_aymy/blog/item/5c9f47aef4f6fbf2faed50c5.html

轉(zhuǎn)載于:https://www.cnblogs.com/jeriffe/articles/1962262.html

總結(jié)

以上是生活随笔為你收集整理的IL语言之.ctor的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。