今天來玩一點變態的,使用反射獲取到某個型別的建構式,接著多次對此型別的某個物件呼叫建構式方法,請問此時會發生什么
假定有一個型別 Foo 的定義如下
class Foo : IDisposable
{
public Foo()
{
}
public int F1 { set; get; }
public int F2 { set; get; } = 10;
}
先使用 RuntimeHelpers 的 GetUninitializedObject 方法創建物件而不呼叫建構式
var foo = (Foo) RuntimeHelpers.GetUninitializedObject(typeof(Foo));
如果給 Foo 的建構式添加斷點,那么在運行上面代碼的時候,可以看到斷點是不會進入,詳細請看 dotnet C# 只創建物件不呼叫建構式方法
此時雖然 Foo 物件 foo 創建了,但是此物件還沒有經過建構式,接下來咱給此物件賦值,請看代碼
var foo = (Foo)RuntimeHelpers.GetUninitializedObject(typeof(Foo));
foo.F1 = 2;
foo.F2 = 2;
請問此時的 Foo 里面的 F1 和 F2 屬性分別是什么?當然就是 2 了
那如果用反射取出建構式,對 foo 物件呼叫建構式呢
var constructorInfo = typeof(Foo).GetConstructor(new Type[0]);
constructorInfo!.Invoke(foo, null);
此時可以看到 foo 物件里面,兩個屬性的值不同,具體是啥?自己去本文末尾拉代碼跑跑看
接著再給 foo 物件賦值,如下面代碼
foo.F1 = 5;
foo.F2 = 5;
然后再次呼叫建構式,如下面代碼
foo.F1 = 5;
foo.F2 = 5;
constructorInfo!.Invoke(foo, null);
請問此時的 F1 和 F2 屬性的值是什么?
回顧一下基礎知識,在類里面寫的 public int F2 { set; get; } = 10; 代碼其實是 C# 語言帶來的功能,在構建的時候,會被轉寫為大概如下的建構式代碼
public Foo()
{
F2 = 10;
}
通過 IL 代碼可以看到實際的邏輯如下
.method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8
// [53 43 - 53 45]
IL_0000: ldarg.0 // this
IL_0001: ldc.i4.s 10 // 0x0a
IL_0003: stfld int32 KicheyurcherNiwhiyuhawnelkeera.Program/Foo::'<F2>k__BackingField'
// [48 13 - 48 25]
IL_0008: ldarg.0 // this
IL_0009: call instance void [System.Runtime]System.Object::.ctor()
IL_000e: nop
// [49 13 - 49 14]
IL_000f: nop
// [50 13 - 50 14]
IL_0010: ret
} // end of method Foo::.ctor
在 C# 中,其實建構式也是一個函式而已,如上面代碼,只有寫給 F2 賦值的邏輯,而沒有給 F1 賦值的邏輯,因此在呼叫建構式的時候,只會改變 F2 屬性的值,而不會更改 F1 屬性的任何值,也因為建構式只是一個函式,因此呼叫多次就和呼叫一個方法多次是一樣的
本文所有代碼放在github 和 gitee 歡迎訪問
可以通過如下方式獲取本文的源代碼,先創建一個空檔案夾,接著使用命令列 cd 命令進入此空檔案夾,在命令列里面輸入以下代碼,即可獲取到本文的代碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 5eb2ea112f2861791fafda9ed326657fd05572dd
以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
獲取代碼之后,進入 KicheyurcherNiwhiyuhawnelkeera 檔案夾
博客園博客只做備份,博客發布就不再更新,如果想看最新博客,請到 https://blog.lindexi.com/

本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可,歡迎轉載、使用、重新發布,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用于商業目的,基于本文修改后的作品務必以相同的許可發布,如有任何疑問,請與我[聯系](mailto:[email protected]),
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/298769.html
標籤:.NET技术
上一篇:C#多執行緒開發-任務并行庫04
