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

C#函數參數傳遞解惑

編輯:C#入門知識

原則:   1、簡單的值類型的數組,每個數組成員是一個引用(指針),引用到棧上的空間(因為值類型變量的內存分配在棧上)   2、引用類型,類類型的數組,每個數組成員仍是一個引用(指針),引用到堆上的空間(因為類的實例的內存分配在堆上)       class Person{}       Person[] myPerson;   myPerson = new Person[2];   myPerson[0] = new Person;   myPerson[1] = new Person;       Persons是一個變量,它是一個可以容納兩個引用空間的內存塊, 因為數組在聲明定義的時候是能夠知道元素個數的,所以在堆棧 上分配的內存空間是預先可以知道的 (這裡的堆棧簡化理解可以理解成為棧,在C++中由系統管理內存, 堆內存的管理是人工的C++中) 兩個引用實際上就是兩個指針變量,在32位機中,myPerson變量就是64字節(2*32)兩個指針變量的內存 空間,這64字節的內存空間名字命名為myPerson   C#語言函數參數的傳遞   就像C語言眾多的後世子孫一樣,C#的函數參數是非常講究的。首先,參數必須寫在函數名後面的括號裡,這裡我們有必要稱其為形參。參數必須有一個參數名稱和明確的類型聲明。該參數名稱只在函數體內部可見。因此在該函數體以外的任何地方使用同樣的變量名是不會引起沖突的。每當調用函數的時候,必須將一個實參傳遞給函數定義中的形參。默認情況下,C#的參數傳遞是值傳遞。這種方式的優點和缺點同樣明顯。另外,在傳送引用類型的時候還時不時引起一些小誤會。更加使人困惑的是,既然CLR不支持指針類型,那麼我們以前在C/C++中的那些關於指針傳遞的妙用應該如何實現呢?不必發愁,本文將會逐一回答上述這些疑問。首先我們會討論默認情況下的值傳遞以及這種方式的優缺點,解釋默認情況下傳遞引用類型時容易產生的誤解。然後,我們討論如何利用ref關鍵字把一個值類型作為引用類型傳遞給參數。最後,我們嘗試著讓一個函數可以返回多個值,在C/C++中我們經常利用指針達到這一目的,這裡我們將會利用out關鍵字重溫這種美妙的感覺。   值傳遞   每當調用一個函數的時候,我們就必須為該函數的每一個形參傳遞一個實參。默認情況下,采用值傳遞的機制。也就是說,實參的值會被拷貝到形參裡面,這樣我們在函數內部得到一個本地變量,該變量的值和傳遞進來的那個實參的值相等,但是它們存放在不同的存儲空間。因此,我們對函數參數所做的一切實際上都是對函數提內本地變量的操作,絕對不會影響到作為實際參數傳遞過來的那個函數體外的變量。看下面的例子,我就不再多費口舌了。   using System;   namespace CS語言函數參數的傳遞 {      /// <summary>      /// Class1 的摘要說明。      /// </summary>      class Example      {          static void Main(string[] args)          {               int argument = 5;               Example exp = new Example();                 System.Console.WriteLine(argument);                 exp.fun1(argument);                 System.Console.WriteLine(argument);          }            public Example()          {          }            public void fun1(int parameter)          {               //對parameter的操作實際上是對本地變量的修改               //不會影響到函數體外作為實參傳遞過來的變量               parameter += 5;               System.Console.WriteLine(parameter);          }      } }   但是值傳遞的機制有一個明顯的缺點。主要表現在值類型的傳遞方面。我們對參數的修改會在函數體執行結束之際消失。如果我們希望將這種變化影響到作為實參傳遞過來的那個函數體以外的變量就必須把值類型作為引用類型傳遞。後邊會具體討論。值傳遞機制的另一個缺點,或許你會認為這是一個優點,表現在引用類型的傳遞方面。按照值傳遞的機制傳遞一個引用類型的變量,實際上只是完成了一次淺拷貝。請不要誤認為對整個對象進行了深拷貝。函數參數得到的只是實參的handle的值。也就是說,本地的參數實際上只是一個引用類型的handle,和作為實參傳遞過來的那個變量的handle具有相同的值,指向同一個object(兩個handle指向堆上的相同位置)。這樣我們在函數內部對參數所做的修改會直接影響到堆上的object。當函數結束之後,本地的參數消失,而對於堆上的object的修改會成為持久的修改而繼續保留下來。   把值類型作為引用類型傳遞   有一些時候,我們不惜望函數對於參數的修改隨著函數的結束而消失。作為引用類型,作到這一點其實一點都不難,就像我們上面說的那樣。但是,如果是值類型的參數,似乎就有一點麻煩了。從前在C/C++裡面可以采取傳遞指針的方法來達到這個目的。但是CLR已經明確取消了指針。作為補償,C#為我們提供了ref關鍵字。ref關鍵字通知編譯器,參數的實參是作為引用類型而非值類型進行傳遞。下面的這段程序幫助我們說明問題。   using System;   namespace CS語言函數參數的傳遞 {      class Example      {          static void Main(string[] args)          {               int argument = 5;               Example exp = new Example();                 //首先顯示argument               System.Console.WriteLine(argument);               exp.fun2(ref argument);//傳遞參數時必須使用ref關鍵字               System.Console.WriteLine(argument);                 System.Console.ReadLine();          }            public void fun1(int parameter)          {               //對parameter的操作實際上是對本地變量的修改               //不會影響到函數體外作為實參傳遞過來的變量               parameter += 5;               System.Console.WriteLine(parameter);          }            public void fun2(ref int parameter)          {               parameter += 5;               System.Console.WriteLine(parameter);          }      } }   函數fun2要求一個int類型的參數,並且伴有關鍵字ref。在Main()函數內定義了一個整形變量argument,它將會作為實參傳遞給函數fun2()。在調用該函數之前,首先顯示了變量argument,其值等於5。緊接著調用函數fun2(),並且傳遞argument給參數parameter。這時函數得到的是一個本地的,指向整形變量argument的handle。在函數內部,把parameter加5,然後顯示它。這時其值為10。函數返回後再一次顯示argument,其值同樣為10。   讓函數返回多個返回值   有些時候我們可能會希望一個函數可以返回多個返回值。事實上,這是不可能的因為一個函數只能返回一個返回值。但是我們確實辦法達到這種效果。最簡單的是下面這種方法。   public int fun3(ref int i, int j)          {               i = j;                 return i + j;          }   我們這樣調用這個函數。   int i;               int sum = exp.fun3(ref i, 10);               System.Console.WriteLine(i);               System.Console.WriteLine(sum);   這樣在執行過函數fun3()之後,我們實際上得到了i的值和i + j的值。實際上起到了利用一個函數返回兩個值的作用。另外有一個關鍵字也是非常重要的。那就是out關鍵字。該關鍵字允許向參數傳遞一個沒有分配空間的引用類型。利用這個關鍵字同樣可以達到返回多個值的目的。   public void fun4(ref int i, out object obj)          {               i+=5;               obj = i.ToString();               System.Console.WriteLine(i);               System.Console.WriteLine(obj);          }   上面這個方法要求兩個參數。第二個參數要求一個object類型的變量。該參數前面有一個out關鍵字。編譯器會認為該參數的實參沒有被分配存儲空間。Out參數在未被賦值之前不能使用。可以這樣調用該函數:   int i = 5;               object obj;               exp.fun4(ref i, out obj);               System.Console.WriteLine(i);               System.Console.WriteLine(obj);   輸出為4個10。說明我們在調用該函數之後得到了變量i和obj兩個變量的值。

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