更正 值型別並不總是分配在棧上

2021-09-25 04:20:16 字數 1675 閱讀 3880

問:.net中值型別和引用型別的區別是什麼?

答:值型別分配在棧上,引用型別分配在堆上。

這樣的問答我見過無數無數,很慚愧,

我也曾經說過這樣的話

,實在抱歉,特此更正。

我不是學院派的,但是既然要寫點東西出來,查點資料還是必須的,所以我又翻開了寶典——「噹噹噹噹!」——《clr via c#》,書中是這麼描述的:

引用型別總是從託管堆上分配的,嘰裡呱啦嘰裡呱啦……

使用引用型別時,必須注意到可能存在的一些效能問題,嘰裡呱啦嘰裡呱啦……

為了提公升簡單的常用型別的效能,clr提供了名為「值型別」的輕量級型別。值型別的例項通常是在乙個執行緒的堆疊上分配的,嘰裡呱啦嘰裡呱啦……

注意到了嗎,誰也沒說值型別就一定在棧上分配啊,人家只是說通常。而且這部分內容應該是jeffrey直接從《.net framework programming》一書中直接拷貝(繼承)過來的,ctrl+c & ctrl+v,***。

但是由於撰文的邏輯,和段落的安排,這一處的描述很容易讓人理解為:

引用型別一定是在堆上的,沒錯,引用型別會存在效能問題,也沒錯,所以出現了傳說中的值型別,嗯嗯,所以值型別是分配在…………哈?

那麼好吧,回歸原點。「值」型別,對,是「值」型別,沒人叫他「棧」型別吧。

這也就說明了值型別應該被關注的特徵是它是copy by value的,而不是它具體是分配在什麼地方的。然而在目前,顯然,大多數人提到值型別,第乙個想到的是它是分配在棧上,而不是它的copy by value特性,這樣也引發了很多很多的bug!!

好吧,說了這麼多,舉一些例項吧。

1. 引用型別裡面的成員變數,即使是值型別的,也會和引用型別的例項一起被分配到堆上。

2. 值型別的陣列。陣列是引用型別的,所以裡面的值也都會在堆上。

哦?你好像明白了?作為引用型別內部的成員的值型別是會隨著引用型別被分配到堆上的。

所以,只有所有的本地值型別的區域性變數會被分配到棧上!?

呃,先看下面這段code:

/// /// interaction logic for window2.xaml

///

public partial class window2 : window

private void foo()

}

14行的number變數是值型別,也是區域性變數,但是它在棧上嗎?顯然不在,不然button click的時候它怎麼被顯示出來。

其實.net在處理閉包的時候,會生成乙個輔助類,並把閉包內的變數設定成為這個輔助類的成員變數。所以根本上,這個情況跟第一點還是一樣的,只是更加隱蔽而已。(匿名委託和lambda表示式的出現導致了這個杯具,@jeffrey)

3. 閉包內的區域性值型別變數也會被分配到堆上。

所以今後一定要嚴記,值型別和引用型別的區別,不是分配到**的關係,而是跟他們的名字一樣,乙個是copy by value,乙個是copy by reference。

*無責任備註:面試的時候如果被問到這個,最好多做些解釋,而不要直接說結論,因為你的面試官可能也認為它們的區別只是分配到棧上和堆上,因為這個丟了工作就不好了。

TCP並不總是「可靠」的?

1.當對方意外崩潰後 如斷電或網路中斷 並且沒有發出fin包時,處於傳送端無法得知這種情況,處於傳送緩衝區的資料會不斷向對方傳送,但由於對方離開會不斷因為超時重傳,重傳12次左右 大概9分鐘 依然沒有響應就會返回乙個超時通知 如果傳送端此時有乙個read操作會讀取到這個訊號,但如果在之後你繼續通過這...

TCP並不總是「可靠」的?

tcp 是可靠的?傳送端通過呼叫send函式之後,資料流並沒有傳輸出去,資料會先儲存到套接字的傳送緩衝區中,通過網路協議棧決定何時傳送 如何傳送。當對應的資料傳送給接收端,接收端回應ack,這時儲存到傳送緩衝區的資料可以刪除了,但傳送端無法獲取對應資料流的ack情況 無法判斷對端是否接收到資料流 如...

新的並不總是最好的

不知道大家是否接受這種觀點 新的並不總是最好的 new doesn t always mean better.我們在平時習慣於接受新的產品,立刻放棄舊的,我們習慣於對新產品的追逐,新產品給我們帶了對未來希望的憧憬,它給我們煩悶的生活注入新鮮,讓我們為之一振,讓我們感受到我們還活在不斷前進的社會中,與...