有關ref和out原理問題

2021-10-06 09:48:44 字數 2605 閱讀 5012

想問一下大佬們,ref和out是把值型別轉化為引用型別了嗎?按理來說值型別就是值型別,怎麼會轉為引用型別?能不能詳細講解一下!感謝!!!

封箱、拆箱

引數是什麼型別還是什麼型別,不會改變的

引用型別不用ref或out,都是在堆上,改變了資料就會影響原來的

而值型別不用的話就會重新分配乙個位址,用上了就用原來的位址

不要太深究。

object是萬物的基類。

值型別和引用型別都派生自object。

而object自己是引用型別。

你說,那引用型別,怎麼就生出乙個值型別的小孩了呢?

對對,我繞進去了,可以通過裝箱和拆箱操作進行轉化,不過ref和out好像並沒有進行裝箱操作

大哥,我也不想深究,面試問這個啊

根據大佬們的解釋以及我又查了資料,我重新理解為這樣的:值型別其實也包含位址和值,不過看上去都是自身,平時變數間傳遞是值的傳遞,用ref/out修飾形參後傳遞給形參的是位址,c#在底層**應該會判斷各種情況並加以標識。我只能這樣理解了

ref/out引用傳遞本身沒有用到"封箱、拆箱"。

ref/out的dotnet的實現無非就是傳遞乙個『記憶體位址』。

比如有乙個結構my

struct my

執行後乙個my的例項1在記憶體裡的布局將類似(17821540等數字,是記憶體位址):

17821540:

--> 17821544:a

17821548:b

17821552:c

17821556:d

乙個int占用4個位元組的記憶體,可以看到,b跟在a的後面,c跟在b的後面,d跟在c的後面,記憶體偏移都是4個位元組。

如果我們把17821544傳給某個過程,而該過程修改了記憶體17821548下的內容,實際上就等於修改例項1的b的值。

我們可以理解成17821544就是例項1的『引用』,傳遞17821544的方式就是ref引用傳遞。

相形之下,按值傳遞則是拷貝了整個例項1的a,b,c,d的值,共4個int。按值傳遞後,過程對傳入引數的修改,將修改到乙個臨時的記憶體拷貝下,不會影響到原來的例項1。

以下的示例**需要設定專案屬性/編譯/允許unsafe:

unsafeclassprogram

staticvoidbyref(refmy my)

}

staticvoidbyval(my my)

}

structmy

}

我的機器的執行結果為:

[ main] address of my:   17821544

[ main] address of my.b: 17821548

[byref] address of my:   17821544

[byref] address of my.b: 17821548

[byval] address of my:   17821432

[byval] address of my.b: 17821436

可以看到,在【byref】過程中,除錯列印出的結構位址和【main】呼叫方中結構位址是一樣的,這就是按引用傳遞的實現。

可以看到,在【byval】過程中,除錯列印出的結構位址和【main】呼叫方中結構位址是不一樣,因為byval過程中得到的是乙個臨時拷貝。

注:這裡可以理解成17821544就是例項1的『引用』。但嚴格意義上它不是dotnet所謂的引用.

乙個int占用4個位元組的記憶體,可以看到,b跟在a的後面,c跟在b的後面,d跟在c的後面,記憶體偏移都是4個位元組。

如果我們把17821544傳給某個過程,而該過程修改了記憶體17821548下的內容,實際上就等於修改例項1的b的值。

我們可以理解成17821544就是例項1的『引用』,傳遞17821544的方式就是ref引用傳遞。

相形之下,按值傳遞則是拷貝了整個例項1的a,b,c,d的值,共4個int。按值傳遞後,過程對傳入引數的修改,將修改到乙個臨時的記憶體拷貝下,不會影響到原來的例項1。

這也太本質了吧,贊!!

ref和out的原理及區別

一 建立ref引數 在使用引數時,將引數傳遞給方法使用,而方法中對此值的任何改變並不能影響方法外部的變數。下面乙個例子,控制台輸出4,並沒有對變數進行增量。例如 class reforout public static void main string args i console.readline...

C 中ref和out的原理

去年在csdn 上寫的,現在把它搬過來。用了那麼久的ref和out,你真的了解它們是如何使得實參與形參的值保持同步的嗎?要研究這個問題,前提是要了解c 中方法間引數是如何傳遞的 1.clr支援兩種型別 值型別和引用型別。表示引用型別 2class ref312 13 1415 static void...

使用ref和out引數

ref型別引數側重修改,out型別引數側重輸出 ref在傳入值之前必須先初始化 out在函式內,函式結束之前,即傳出值之前初始化.eg protected void page load object sender,eventargs e int indexref 1 testref ref inde...