西西軟件下載最安全的下載網站、值得信賴的軟件下載站!

首頁編程開發(fā)C#.NET → c# 引用類型方法參數的關鍵字ref深度解析

c# 引用類型方法參數的關鍵字ref深度解析

相關軟件相關文章發(fā)表評論 來源:西西整理時間:2012/11/21 14:46:13字體大。A-A+

作者:西西點擊:0次評論:0次標簽: 引用類型

昨天在壘代碼的時候遇到了一個基礎沒打牢就會暴露的問題。傳遞給方法的參數為類(class)時,在方法中所做的修改賦值不一定會最終改變到原始的變量上。

舉一個例子,如果一個方法Action(List<int> lst),在方法里面對lst做了很多操作,包括add,remove,new,add等等。傳入變量List<int> input,方法執(zhí)行完之后,input可能被執(zhí)行了add,remove,但是new以后的任何操作都沒有保留。這是為什么呢?最開始學習.net基礎的時候就知道,引用類型,傳遞給方法的是引用的地址,而不是實際數值。那為什么會部分的操作被保留了出來,而部分又沒有執(zhí)行呢?

用代碼來分析此案例:

static void Main(string[] args)
{   
    int i = 0;
    int refI = 0;
    List<int> list = new List<int>() { 0, 1, 2 };
    List<int> refList = new List<int>() { 0, 1, 2 };
    testStruct(i);
    TestRefStruct(ref refI);
    TestClass(list);
    TestRefClass(ref refList);
    Console.WriteLine("i: {0}\r\nrefI: {1}\r\nlist: {2}\r\nrefList: {3}", i, refI,
      list.Select(x => x.ToString()).Aggregate((x, y) => x + "," + y),
      refList.Select(x => x.ToString()).Aggregate((x, y) => x + "," + y));
    Console.ReadKey();
}

static void TestStruct(int input)
{
    input = 10;
}

static void TestRefStruct(ref int input)
{
    input = 10;
}

static void TestClass(List<int> input)
{
    input.Add(5);
    input = new List<int>();
    input.Add(10);
}

static void TestRefClass(ref List<int> input)
{
    input.Add(5);
    input = new List<int>();
    input.Add(10);
}

調試程序,最后輸出

i: 0
refI: 10
list: 0,1,2,5
refList: 10

在函數TestStruct中,傳入一個值類型的參數,沒有對傳遞進去的參數i做任何的修改。

在函數TestRefStruct中,傳入值類型的參數,通過引用傳遞參數ref,函數中對input進行的任何改變都影響到了refI上,所做的編輯修改全部保留過來。最終refI的值為10。

在函數TestClass中,傳入一個引用類型的參數,在函數中,對input重新賦值之前所做的修改都保留了下來,影響了list的值。而在對input重新賦值之后的所有修改編輯,都和list沒有任何關聯了。

在函數TestRefClass中,傳入一個引用類型的參數,同時,參數前面加上ref的約束,函數中,對input進行的任何編輯都影響了refList。最終refList的值為new List<int>{ 10 }。

有一定.net基礎的人都可以很清晰的理解第一、二和第四種情況。但是第三種情況常常會給我們留下陷阱。

如何理解和正確的對待函數傳遞的參數為引用類型的情況?我的理解是:

第三種情況下,傳遞給函數的變量A提供的是一個引用地址,函數會自動生成一個變量B,同時用傳遞進來的引用地址對這個變量B賦值,這時,傳遞進來的變量A和函數內調用的變量B共一個引用地址,所做的修改會同步的影響另一個參數。如果在函數內部,出現了一個input = new List<int>();的語句。這時,變量B會重新賦值到另一個引用地址。那么,從此之后,變量B與變量A再沒有關聯,對變量B所做的任何修改將不影響變量A。

下面模擬代碼呈現:

List<int> A = new List<int>() { 0, 1, 2 };//傳遞給函數的變量。

{//進入函數
    List<int> B = A;//函數執(zhí)行后,自動生成B,同時用A對B賦值。
    B.Add(5);//由于他們是引用類型,共一個引用地址,所做修改相互影響。此時A的值也一起改變。
    B = new List<int>();//對B重新賦值,指向另一個引用地址。與A無關。
    B.Add(10);//A不變。
}//出函數,B釋放,A繼續(xù)存在。

個人理解。如果不足請補充。

    相關評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    第 2 樓 北京市零度聚陣銀河世紀網吧 網友 客人 發(fā)表于: 2013/5/6 11:17:24
    好高深的東東

    支持( 0 ) 蓋樓(回復)

    第 1 樓 重慶市忠縣 網友 客人 發(fā)表于: 2013/7/14 11:16:57
    繼續(xù)加油

    支持( 0 ) 蓋樓(回復)

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字數: 0/500 (您的評論需要經過審核才能顯示)