ASP.NET堆和棧二之值類型和引用類型的參數(shù)傳遞和內(nèi)存分配
".NET的堆和棧"系列:
ASP.NET堆和棧二之值類型和引用類型參數(shù)傳遞和內(nèi)存分配
ASP.NET堆和棧三之引用類型對象拷貝和內(nèi)存分配
ASP.NET堆和棧四之對托管和非托管資源垃圾的回收和內(nèi)存分配
在" ASP.NET堆和棧一之基本概念和值類型內(nèi)存分配"中,了解了"堆"和"棧"的基本概念,以及值類型的內(nèi)存分配。我們知道:當(dāng)執(zhí)行一個方法的時候,值類型實例會在"棧"上分配內(nèi)存,而引用類型實例會在"堆"上分配內(nèi)存,當(dāng)方法執(zhí)行完畢,"棧"上的實例由操作系統(tǒng)自動釋放,"堆"上的實例由.NET Framework的GC進(jìn)行回收。而本篇的重點要放在:值類型和引用類型參數(shù)的傳遞,以及內(nèi)存分配。
傳遞值類型參數(shù)
class Class1
{
public void Go()
{
int x = 5;
AddFive(x);
Console.WriteLine(x.ToString());
}
public int AddFive(int pValue)
{
pValue += 5;
return pValue;
}
}大致過程如下:
1、值類型變量x被放到"棧"上。

2、開始執(zhí)行AddFive()方法,值類型變量pValue被放到"棧"上,并把x的值賦值給pValue,pValue的值變成了5。

3、繼續(xù)執(zhí)行AddFive()方法,pValue的值變成了10。

4、執(zhí)行完AddFive()方法,釋放pValue的內(nèi)存,"棧"指針回到x,線程重新回到Go()方法中。

輸出結(jié)果:5
以上,在傳遞值類型參數(shù)x的時候,實際上是把x一個字節(jié)一個字節(jié)地拷貝給pValue。
傳遞容易造成"棧溢出"的值類型參數(shù),在值類型參數(shù)前加關(guān)鍵字ref
public struct MyStruct
{
long a, b, c, d, e, f, g, h, i, j, k, l, m;
}
public void Go()
{
MyStruct x = new MyStruct();
DoSomething(x);
}
public void DoSomething(MyStruct pValue)
{
// DO SOMETHING HERE....
}假設(shè)以上的值類型struct足夠大,而x和pValue都會被分配到"棧"上,這時可能造成"棧溢出"。

如何避免呢?
--解決辦法是讓DoSomething傳遞一個ref類型參數(shù)。這樣寫:
public struct MyStruct
{
long a, b, c, d, e, f, g, h, i, j, k, l, m;
}
public void Go()
{
MyStruct x = new MyStruct();
x.a = 5;
DoSomething(ref x);
Console.WriteLine(x.a.ToString());
}
public void DoSomething(ref MyStruct pValue)
{
pValue.a = 12345;
}使用ref后,執(zhí)行DoSomething(ref x),是把x的地址賦值給了pValue,即pValue和x指向了同一個引用地址。當(dāng)改變pValue的值,變化也會反映到x中。

輸出結(jié)果:12345
以上,為了避免"大型"值類型參數(shù)傳遞時造成的"棧溢出",可以在值類型前面加ref關(guān)鍵字,于是,在傳遞值類型參數(shù)x的時候,實際上是把x本身的棧地址拷貝給pValue,x和pValue指向同一個棧地址。
傳遞引用類型參數(shù)
傳遞引用類型參數(shù)的道理和在傳遞的值類型參數(shù)前面加ref關(guān)鍵字是一樣的。
public class MyInt
{
public int MyValue;
}
public void Go()
{
MyInt x = new MyInt();
x.MyValue = 2;
DoSomething(x);
Console.WriteLine(x.MyValue.ToString());
}
public void DoSomething(MyInt pValue)
{
pValue.MyValue = 12345;
}輸出結(jié)果:12345
以上大致過程是這樣:
1、在托管堆上創(chuàng)建一個MyInt類型的實例
2、在棧上創(chuàng)建一個MyInt類型的變量x指向堆上的實例
3、把托管堆上的公共字段MyValue賦值為2
4、通過DoSomething(x)方法,把x的引用地址賦值給pValue,即pValue和x指向同一個引用地址
5、改變pValue的值,也會反映到x上
以上,在傳遞引用類型參數(shù)x的時候,實際上是把x指向托管堆實例的引用地址拷貝給pValue,x和pValue指向同一個托管堆實例地址。
傳遞引用類型參數(shù),在引用類型參數(shù)之前加關(guān)鍵字ref
public class Thing
{
}
public class Animal:Thing
{
public int Weight;
}
public class Vegetable:Thing
{
public int Length;
}
public void Go()
{
Thing x = new Animal();
Switcharoo(ref x);
Console.WriteLine("x is Animal : " + (x is Animal).ToString());
Console.WriteLine("x is Vegetable : " + (x is Vegetable).ToString());
}
public void Switcharoo(ref Thing pValue)
{
pValue = new Vegetable();
}輸出結(jié)果:
x is Animal : False
x is Vegetable : True
以上大致過程是這樣:
1、在托管堆上創(chuàng)建Animal對象實例。
2、在棧上創(chuàng)建類型為Thing的x變量指向Animal實例的引用地址。
3、通過Switcharoo(ref x)方法把x本身的地址賦值給pValue,至此,pValue和x指向了相同的棧內(nèi)存地址,任何一方的變化都會反映到另外一方。

4、在Switcharoo(ref Thing pValue)內(nèi)部,在托管堆上創(chuàng)建Vegetable對象實例。
5、pValue指向Vegetable實例,也就相當(dāng)于x指向Vegetable實例。

以上,當(dāng)在引用類型參數(shù)之前加上關(guān)鍵字ref,再傳遞,是把x本身的棧地址拷貝給pValue,x和pValue指向同一個棧地址。
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
asp.net下Linq To Sql注意事項小結(jié)
對于Linq 連接數(shù)據(jù)庫進(jìn)行操作時需注意的問題2008-10-10
MongoDB.Net工具庫MongoRepository使用方法詳解
這篇文章主要為大家詳細(xì)介紹了MongoDB.Net工具庫MongoRepository的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
asp.net aspnetpager分頁統(tǒng)計時與實際不符的解決辦法
最近分頁方面根據(jù)實際需要修改了一些函數(shù)2008-11-11
AspNetCore&MassTransit?Courier實現(xiàn)分布式事務(wù)的詳細(xì)過程
MassTransit?Courier是一種用于創(chuàng)建和執(zhí)行帶有故障補(bǔ)償?shù)姆植际绞聞?wù)的機(jī)制,它可以用于滿足本地事務(wù)的需求,也可以在分布式系統(tǒng)中實現(xiàn)分布式事務(wù),這篇文章主要介紹了AspNetCore&MassTransit?Courier實現(xiàn)分布式事務(wù),需要的朋友可以參考下2022-10-10
.NET開發(fā)人員關(guān)于ML.NET的入門學(xué)習(xí)
隨著谷歌,F(xiàn)acebook發(fā)布他們的工具機(jī)器學(xué)習(xí)工具Tensorflow 2和PyTorch,微軟也發(fā)布了ML.NET 1.0??梢哉f2019年是機(jī)器學(xué)習(xí)社區(qū)普及化的一年,下面小編向大家簡單介紹一下關(guān)于ML.NET的入門學(xué)習(xí)2019-05-05
C#調(diào)用C++版本dll時的類型轉(zhuǎn)換需要注意的問題小結(jié)
最近使用C#調(diào)用C++版本的dll遇到很多類型轉(zhuǎn)換的問題,現(xiàn)記錄出容易出錯的部分。2010-04-04
ASP.NET頁面某些選項進(jìn)行提示判斷具體實現(xiàn)
針對asp.net頁面某些選項進(jìn)行提示判斷,比如當(dāng)保存一個信息時候,需要對當(dāng)前信息是否為空進(jìn)行判斷2013-06-06
基于.NET?7?的?QUIC?實現(xiàn)?Echo?服務(wù)的詳細(xì)過程
這篇文章主要介紹了基于.NET?7?的?QUIC實現(xiàn)Echo服務(wù),下面的內(nèi)容中,我會介紹如何在.NET?中使用?Quic,文中結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-11-11

