程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 從賦值操作理解不同類型的函數傳參

從賦值操作理解不同類型的函數傳參

編輯:C#入門知識

我們都知道所謂的程序,就是對傳入的數據進行操作,最終將處理的數據輸出給用戶。那麼在我們的編程中的體現,就是通過函數(或者方法)參數傳入數據,然後通過函數返回值輸出處理後的數據。數據的傳入涉及到函數的實參和形參的傳遞,數據的輸出涉及到函數的返回值和返回值類型的參數。函數返回值沒有什麼特別之處,而其他的都是函數傳參的問題,既然是傳參,那麼傳參到底傳過去了什麼?
函數傳參與賦值操作

         我們都知道函數傳參涉及到形參和實參,那麼實參和形參就是兩個不同的變量,所以函數傳參的過程,類似(或者說就是)使用實參給形參賦值的過程。那麼我們先來分析按值傳參的情況

         圖1是值類型變量的賦值操作圖,我們大家都知道值類型變量直接保存變量的內容,所以賦值的過程就是將ValA保存的內容直接拷貝到ValB中,此時兩個變量除了保存的值相同外,沒有其他的任何關系,所以此時修改ValB的內容並不會引起ValA的變化。這是與值類型按值傳參的效果是一樣的。

 

圖 1.值類型變量賦值

 

         圖2展示的是引用類型變量的賦值操作,我們都知道引用類型的變量保存的是一個地址,這個地址指向了變量內容所在的地址,也就是說引用變量保存的是一個地址。那麼引用類型的賦值操作同樣也是拷貝變量保存的內容,這樣ValA和ValB就都指向了同樣地址。如果我們修改ValB的成員,那麼ValA中也會隨之產生變化。我們可以看到值類型和引用類型的賦值操作是一樣的,都是對變量直接保存的內容的拷貝過程。但是如果我們使用其他對象對ValB重新賦值,這時ValB就指向了其他對象,ValA還指向原來的對象並沒有變化。

 

圖 2. 引用類型變量賦值

 

         我們知道C#中引入了ref關鍵字,使我們可以通過函數參數返回函數的處理結果,對於我們需要同時返回多項結果的時候比較有用。其實這也就是我們通常所說的按引用傳參。圖3展示了變量地址賦值操作,此時我們使用新的對象對ValB所指定的對象賦值,這是ValA也就指向了新的對象了。C#中的ref是否也是這樣操作的呢?我們看以看一下下邊的代碼和相應的IL就知道了。

 

圖 3. 變量地址賦值操作

C#代碼

[csharp] 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
 
namespace FunctionParameter 

    class PassByValue 
    {        
        public void PassValueParameterByReference(ref ReferencePara parameter) 
        { 
            parameter.a = 1; 
            parameter = new ReferencePara(); 
        } 
 
        public class ReferencePara 
        { 
            public int a; 
            public int b; 
        } 
    } 

[csharp] 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
 
namespace FunctionParameter 

    class PassByValue 
    {        
        public void PassValueParameterByReference(ref ReferencePara parameter) 
        { 
            parameter.a = 1; 
            parameter = new ReferencePara(); 
        } 
 
        public class ReferencePara 
        { 
            public int a; 
            public int b; 
        } 
    } 

對應的MSIL代碼

[csharp] 
//傳遞的是變量的地址  
.method public hidebysig instance void  PassValueParameterByReference(class FunctionParameter.PassByValue/ReferencePara& parameter) cil managed 

  // 代碼大小       17 (0x11)  
  .maxstack  8 
  IL_0000:  nop 
  //加載參數  
  IL_0001:  ldarg.1 
  //加載對象的引用  
  IL_0002:  ldind.ref 
  IL_0003:  ldc.i4.1 
  IL_0004:  stfld      int32 FunctionParameter.PassByValue/ReferencePara::a 
  IL_0009:  ldarg.1 
  IL_000a:  newobj     instance void FunctionParameter.PassByValue/ReferencePara::.ctor() 
  //綁定對象的引用  
  IL_000f:  stind.ref 
  IL_0010:  ret 
} // end of method PassByValue::PassValueParameterByReference 
[csharp] view plaincopy
//傳遞的是變量的地址 
.method public hidebysig instance void  PassValueParameterByReference(class FunctionParameter.PassByValue/ReferencePara& parameter) cil managed 

  // 代碼大小       17 (0x11) 
  .maxstack  8 
  IL_0000:  nop 
  //加載參數 
  IL_0001:  ldarg.1 
  //加載對象的引用 
  IL_0002:  ldind.ref 
  IL_0003:  ldc.i4.1 
  IL_0004:  stfld      int32 FunctionParameter.PassByValue/ReferencePara::a 
  IL_0009:  ldarg.1 
  IL_000a:  newobj     instance void FunctionParameter.PassByValue/ReferencePara::.ctor() 
  //綁定對象的引用 
  IL_000f:  stind.ref    www.2cto.com
  IL_0010:  ret 
} // end of method PassByValue::PassValueParameterByReference 

 

 

 

總結

         從我們大學一開始接觸計算機編程開始,我們就開始記憶兩種函數傳參的異同,其實傳參的過程就是實參對形參賦值的過程,只不過有時拷貝的是變量的內容,有時拷貝的是變量的地址罷了。
作者:xuhongwei0411

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved