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。
- 可以轉載該博客,但必須著名博客來源。