out和ref詳解


1   概述

根據個人經驗,充分理解out和ref的前提是了解值類型和引用類型的傳遞過程,因此本篇文章先介紹值類型和引用類型,再結束out和ref。

2   值類型和引用類型

2.1   值類型

(1)值類型Code

    通過值的方式來傳遞,即實際參數向形式參數傳遞(關於形參和實參術語,這里不定義),主要存儲在棧中。通過值傳遞,copy副本形式,調用棧的Pop()和Push()方法來實現。 常見類型:int,float,bool,enum,struct,Array等。

 例子:

 1         //主函數
 2         static void Main(string[] args)  3  {  4             //定義兩個實參n1和n2,並初始化
 5             int n1 = 10, n2 = 20;  6             Console.WriteLine("交換前n1和n2的值");  7             Console.WriteLine("n1={0},n2={1}", n1, n2);//n1=10,n2=20
 8  Swap(n1,n2);  9             Console.WriteLine("交換后n1和n2的值"); 10             Console.WriteLine("n1={0},n2={1}",n1,n2);//n1=10,n2=20
11  Console.Read(); 12  } 13 
14         /// <summary>
15         /// 交換兩個變量的值 16         /// </summary>
17         /// <param name="n1">形參n1</param>
18         /// <param name="n2">形參n2</param>
19        static private void Swap(int t1,int t2) 20  { 21             int temp; 22             temp =t1; 23             t1 =t2; 24             t2 = temp; 25         }

(2)值類型分析

  以上代碼,通過值傳遞,交換兩個變量后,並沒有改變n1和n2的值,根本原因是,值傳遞是通過copy副本形式,不改變原值。圖如下:

a.定義變量n1和n2,並初始化變量,在內存中的表示大致如下( int n1 = 10, n2 = 20;)   

Code調試

在內存中表示

 b.執行交換變量方法時

Code調試

在內存中表示

 交換詳細步驟示意圖

 

2.2  引用類型

(1) 引用類型Code

     引用類型通過地址來傳遞,如c++中的指針。通俗地講,把地址當作開門的鑰匙即可,主要存儲在堆中。通過地址來傳遞,共享變量,一個改變,所有改變,常見類型有String,Object等。

 1 // Cpplus.cpp : 定義控制台應用程序的入口點。  2 //  3 
 4 #include "stdafx.h"
 5  
 6 //主函數
 7 int _tmain(int argc, _TCHAR* argv[])  8 {  9     void Swap(int *x, int *y); 10     int n1 = 10, n2 = 20; 11     printf("交換前n1和n2的值\n"); 12     printf("%d,%d\n", n1, n2); 13     Swap(&n1,&n2); 14     printf("交換后n1和n2的值\n"); 15     printf("%d,%d",n1,n2); 16  getchar(); 17     return 0; 18 } 19 //交換函數
20 void Swap(int *x, int *y) 21 { 22     int temp = *x; 23     *x = *y; 24     *y = temp; 25 }

result:

(2)分析

示意圖

3    out和ref

3.1  為什么引入out和ref

       由以上分析可知,值傳遞是無法改變變量的值的,若要像c++一樣,改變變量的值,該怎么辦?c#引入了out和ref來解決該問題。因此,out和ref均屬於引用類型。

3.2  out詳解

(1)例子

      //主函數
        static void Main(string[] args) { int n1, n2; Console.WriteLine(GetSum(out n1,out n2)); Console.Read(); } //out參數
       static public int GetSum(out int numberFirst,out int numberSecond) { numberFirst = 10; numberSecond = 3; return numberFirst + numberSecond; }

result:

(2)out特點

a.out只出不進;

b.方法定義和調用方法都必須顯示使用out關鍵字(如上代碼顯然易見);

c.out只出不進,即具有清空方法體外參數功能(如上代碼,讀者可以任意改變n1和n2的值,只要不改變GetSum()方法體,輸出的值均為13);

d.為引用類型(直接調用而不事先定義n1和n2,編譯不通過);

e.同名函數,out不與ref同時存在,可以重載;

//如下兩個方法可以重載
public
void getNumer(int num){} public void setTime(out int num){num=10;}


//如下兩個方法不能重載
public void getNumer(ref int num){num=10;}
public void setTime(out int num){num=10;}

3.3  ref詳解

 (1)例子

     //主函數
        static void Main(string[] args) { int n1=1, n2=3; Console.WriteLine(refGetSum(ref n1,ref n2)); Console.Read(); } //ref參數
       static public int refGetSum(ref int numberFirst, ref int numberSecond) { numberFirst = 10; numberSecond = 3; return numberFirst + numberSecond; }

(2)ref特點

a.有進有出;

b.方法定義和調用方法都必須顯示使用ref關鍵字(如上代碼顯然易見);

c.ref有進有出,即可以把值傳入方法體內(如上代碼,讀者可以任意改變n1和n2的值);

d.為引用類型(直接調用而不事先定義n1和n2,編譯不通過);

e.同名函數,out不與ref同時存在,可以重載;

3.4  out與ref比較

   out只輸出,ref有進有出。

4   版權

 

  • 感謝您的閱讀,若有不足之處,歡迎指教,共同學習、共同進步。
  • 博主網址:http://www.cnblogs.com/wangjiming/。
  • 極少部分文章利用讀書、參考、引用、抄襲、復制和粘貼等多種方式整合而成的,大部分為原創。
  • 如您喜歡,麻煩推薦一下;如您有新想法,歡迎提出,郵箱:2016177728@qq.com。
  • 可以轉載該博客,但必須著名博客來源。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM