c#中使用ref和out传值
首先,如果不使用這兩個關鍵字,那是什么樣 呢?
看下面的例子:
使用ref:
using System;
class Test
{
static void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
static void Main()
{
int i = 1, j = 2;
Swap(ref i, ref j);
Console.WriteLine("i = {0}, j = {1}", i, j);
}
}
程序經編譯后執行輸出:
i = 2, j = 1
不使用:
using System;
class Test
{
static void Swap(int x,int y)
{
int temp = x;
x = y;
y = temp;
}
static void Main()
{
int i = 1, j = 2;
Swap(i,j);
Console.WriteLine("i = {0}, j = {1}", i, j);
}
}
程序經編譯后執行輸出:
i = 1, j = 2;
比較這兩個里子很明顯,使用了ref關鍵字的函數調用以后,i和j的值變化了.而沒有使用ref的卻沒有變,為什么呢?
請看下面這段話:
方法的參數是個值得特別注意的地方。方法的參數傳遞有四種類型:傳值(by value),傳址(by reference),輸出參數(by output),數組參數(by array)。傳值參數無需額外的修飾符,傳址參數需要修飾符ref,輸出參數需要修飾符out,數組參數需要修飾符params。傳值參數在方法調用過程中如果改變了參數的值,那么傳入方法的參數在方法調用完成以后并不因此而改變,而是保留原來傳入時的值。傳址參數恰恰相反,如果方法調用過程改變了參數的值,那么傳入方法的參數在調用完成以后也隨之改變。實際上從名稱上我們可以清楚地看出兩者的含義--傳值參數傳遞的是調用參數的一份拷貝,而傳址參數傳遞的是調用參數的內存地址,該參數在方法內外指向的是同一個存儲位置。
所以我們可以看出,平時我們寫的函數參數是傳值參數(傳值參數無需額外的修飾符),不論他是值類型還是引用類型.你可以試這個例子(這個例子是對"不論他是值類型還是引用類型"這句話,):
using System;
class Test
{
static void Swap(string x,string y)
{
string temp = x;
x = y;
y = temp;
}
static void Main()
{
string i = "1", j = "2";
Swap(i,j);
Console.WriteLine("i = {0}, j = {1}", i, j);
}
}
程序經編譯后執行輸出:
i = "1", j = "2";
注意:string類型是引用類型.
i,j的值并沒有改變,說明引用類型作為函數參數時,只要不加ref或者out,那他仍然是傳值參數(我一直以為值類型作為函數參數時是傳值參數,而引用類型作為函數參數時是傳址參數).
.net框架程序設計(修訂版)上有這樣一句話:ref和out的區別是參數的初始化和參數返回,
可是這里說out是輸出參數,那加out是傳址參數嗎?要不,怎么也會變呢(應該也是吧,可能他只是一個名字,可以理解成輸出參數也是傳址參數)?
using System;
class Test
{
static void Swap(out int x, out int y)
{
int temp = x;
x = y;
y = temp;
}
static void Main()
{
int i = 1, j = 2;
Swap(out i, out j);
Console.WriteLine("i = {0}, j = {1}", i, j);
}
}
程序經編譯后執行輸出:
i = 2, j = 1
總結:傳值參數傳遞的是調用參數的一份拷貝,而傳址參數傳遞的是調用參數的內存地址,該參數在方法內外指向的是同一個存儲位置.
這句話可以這樣說更加明白:傳值參數傳遞的是調用參數的拷貝的地址,該參數在方法內外指向的不是是同一個存儲位置,而傳址參數傳遞的是調用參數的內存地址,該參數在方法內外指向的是同一個存儲位置
?
下面是我對2個參數測試結果:
??
?
代碼 using?System;using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
namespace?ref_out
{
????class?Program
????{
????????static?void?Main(string[]?args)
????????{
????????????int?a,?b;
????????????//使用out傳值前實參可以不賦值,即使賦值也沒用,也會被清空
????????????outTest(out?a,?out?b);
????????????Console.Write("a={0},b={1}",?a,?b);
????????????//即使賦值也沒用,也會被清空
????????????int?c?=?1,?d?=?2;
????????????outTest(out?c,?out?d);
????????????Console.Write("a={0},b={1}",?c,?d);
????????????//int?e,?f;//錯誤:ref使用前,變量必須賦值?
????????????//ref使用前,變量必須賦值?
????????????int?e?=?1,?f?=?2;
????????????refTest(ref?e,?ref?f);
????????????Console.WriteLine("e={0};f={1}",?e,?f);
????????}
????????static?void?outTest(out?int?x,?out?int?y)
????????{
????????????//定義out參數的時候就需要對參數進行賦值,即參數需要初始化
????????????x?=?100;?y?=?20;
????????}
????????static?void?refTest(ref?int?x,?ref?int?y)
????????{
????????????//x,y?可以不賦值,參數可以不初始化,把下面注釋掉也可以
????????????x?=?100;?y?=?200;
????????}
????}
}
?
1、使用ref型參數時,傳入的參數必須先被初始化。對out而言,必須在方法中對其完成初始化。
2、使用ref和out時,在方法的參數和執行方法時,都要加Ref或Out關鍵字。以滿足匹配。
3、out適合用在需要retrun多個返回值的地方,而ref則用在需要被調用的方法修改調用者的引用的時候。
?
注:在C#中,方法的參數傳遞有四種類型:傳值(by value),傳址(by reference),輸出參數(by output),數組參數(by array)。傳值參數無需額外的修飾符,傳址參數需要修飾符ref,輸出參數需要修飾符out,數組參數需要修飾符params。傳值參數在方法調用過程中如果改變了參數的值,那么傳入方法的參數在方法調用完成以后并不因此而改變,而是保留原來傳入時的值。傳址參數恰恰相反,如果方法調用過程改變了參數的值,那么傳入方法的參數在調用完成以后也隨之改變。實際上從名稱上我們可以清楚地看出兩者的含義--傳值參數傳遞的是調用參數的一份拷貝,而傳址參數傳遞的是調用參數的內存地址,該參數在方法內外指向的是同一個存儲位置。
方法參數上的 ref 方法參數關鍵字使方法引用傳遞到方法的同一個變量。當控制傳遞回調用方法時,在方法中對參數所做的任何更改都將反映在該變量中。
若要使用 ref 參數,必須將參數作為 ref 參數顯式傳遞到方法。ref 參數的值被傳遞到 ref 參數。
傳遞到 ref 參數的參數必須最先初始化。將此方法與 out 參數相比,后者的參數在傳遞到 out 參數之前不必顯式初始化。
屬性不是變量,不能作為 ref 參數傳遞。
如果兩種方法的聲明僅在它們對 ref 的使用方面不同,則將出現重載。但是,無法定義僅在 ref 和 out 方面不同的重載。
out
方法參數上的 out 方法參數關鍵字使方法引用傳遞到方法的同一個變量。當控制傳遞回調用方法時,在方法中對參數所做的任何更改都將反映在該變量中。
當希望方法返回多個值時,聲明 out 方法非常有用。使用 out 參數的方法仍然可以返回一個值。一個方法可以有一個以上的 out 參數。
若要使用 out 參數,必須將參數作為 out 參數顯式傳遞到方法。out 參數的值不會傳遞到 out 參數。
不必初始化作為 out 參數傳遞的變量。然而,必須在方法返回之前為 out 參數賦值。
屬性不是變量,不能作為 out 參數傳遞。
?
posted on 2009-12-15 23:34 搏擊的小船 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/guanjie20/archive/2009/12/15/1625181.html
總結
以上是生活随笔為你收集整理的c#中使用ref和out传值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运算放大器的输入和输出限制
- 下一篇: 如何实现在一个网页中弹出多个不同的小窗口