天天看點

.net 中 ref out params的差別

C#中有三個關鍵字-ref,out ,params,雖然本人不喜歡這三個關鍵字,因為它們疑似破壞面向對象特性。但是既然m$把融入在c#體系中,那麼我們就來認識一下參數修飾符ref,out ,params吧,還有它們的差別。

NO.1 params

一個可以讓方法(函數)的擁有可變參數的關鍵字。

原則:在方法聲明中的 params 關鍵字之後不允許任何其他參數,并且在方法聲明中隻允許一個 params 關鍵字。

示例(拷貝到vs2005中即可用,下面不再說明)

public partial class Form1 : Form

...{

public static void UseParams(params int[] list)

...{

string temp = "";

for (int i = 0; i < list.Length; i++)

temp = temp +" " +list[i].ToString();

MessageBox.Show(temp);

}

public static void UseParams2(params object[] list)

...{

string temp = "";

for (int i = 0; i < list.Length; i++)

temp = temp + " " + list[i].ToString();

MessageBox.Show(temp);

}

public Form1()

...{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

...{

UseParams(1, 2, 3); //看參數是3個

UseParams(1, 2); //看參數是2個,可變吧

UseParams2(1, 'a', "test");

int[] myarray = new int[3] ...{ 10, 11, 12 };

UseParams(myarray); //看也可以是容器類,可變吧:)

}

}

NO.2 out

這是一個引用傳遞L。

原則一:當一個方法(函數)在使用out作為參數時,在方法中(函數)對out參數所做的任何更改都将反映在該變量中。

原則二:當希望方法傳回多個值時,聲明 out 方法非常有用。使用 out 參數的方法仍然可以傳回一個值。一個方法可以有一個以上的 out 參數。

原則三:若要使用 out 參數,必須将參數作為 out 參數顯式傳遞到方法。out 參數的值不會傳遞到 out 參數。

原則四:不必初始化作為 out 參數傳遞的變量,因為out 參數在進入方法(函數)時後清空自己,使自己變成一個幹淨的參數,也因為這個原因必須在方法傳回之前為 out 參數指派(隻有位址沒有值的參數是不能被.net接受的)。

原則五:屬性不是變量,不能作為 out 參數傳遞。

原則六:如果兩個方法的聲明僅在 out 的使用方面不同,則會發生重載。不過,無法定義僅在 ref 和 out 方面不同的重載。例如,以下重載聲明是有效的:

class MyClass

{

public void MyMethod(int i) {i = 10; }

public void MyMethod(out int i) {i = 10; }

}

而以下重載聲明是無效的:

class MyClass

{

public void MyMethod(out int i) {i = 10; }

public void MyMethod(ref int i) {i = 10; }

}

有關傳遞數組的資訊,請參見使用 ref 和 out 傳遞數組。

示例附後

NO.2 ref

ref僅僅是一個位址!!!

原則一:當一個方法(函數)在使用ref作為參數時,在方法中(函數)對ref參數所做的任何更改都将反映在該變量中。

原則二:調用方法時,在方法中對參數所做的任何更改都将反映在該變量中。

原則三:若要使用 ref 參數,必須将參數作為 ref 參數顯式傳遞到方法。ref 參數的值可以被傳遞到 ref 參數。

原則四:ref參數傳遞的變量必須初始化,因為ref參數在進入方法(函數)時後還是它自己,它這個位址指向的還是原來的值,也因為這個原因ref參數也可以在使用它的方法内部不操作。

原則六:如果兩種方法的聲明僅在它們對 ref 的使用方面不同,則将出現重載。但是,無法定義僅在 ref 和 out 方面不同的重載。例如,以下重載聲明是有效的:

class MyClass

{

public void MyMethod(int i) {i = 10; }

public void MyMethod(ref int i) {i = 10; }

}

但以下重載聲明是無效的:

class MyClass

{

public void MyMethod(out int i) {i = 10; }

public void MyMethod(ref int i) {i = 10; }

}

有關傳遞數組的資訊,請參見使用 ref 和 out 傳遞數組。

示例

public static string TestOut(out string i)

...{

i = "out b";

return "return value";

}

public static void TestRef(ref string i)

...{

//改變參數

i = "ref b";

}

public static void TestNoRef(string refi)

...{

// 不用改變任何東西,這個太明顯了

refi = "on c";

}

public Form1()

...{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

...{

string outi; //不需要初始化

MessageBox.Show(TestOut(out outi)); //傳回值

//輸出"return value";

MessageBox.Show(outi); //調用後的out參數

//輸出"out b";

string refi = "a"; // 必須初始化

TestRef(ref refi); // 調用參數

MessageBox.Show(refi);

//輸出"ref b";

TestNoRef(refi); //不使用ref

MessageBox.Show(refi);

//輸出"ref b";

}

------------------------------------------------------------------------------------------------------------------

在C# 中,既可以通過值也可以通過引用傳遞參數。通過引用傳遞參數允許函數成員更改參數的值,并保持該更改。若要通過引用傳遞參數, 可使用ref或out關鍵字。ref和out這兩個關鍵字都能夠提供相似的功效,其作用也很像C中的指針變量。它們的差別是:

1、使用ref型參數時,傳入的參數必須先被初始化。對out而言,必須在方法中對其完成初始化。

2、使用ref和out時,在方法的參數和執行方法時,都要加Ref或Out關鍵字。以滿足比對。

3、out适合用在需要retrun多個傳回值的地方,而ref則用在需要被調用的方法修改調用者的引用的時候。

注:在C#中,方法的參數傳遞有四種類型:傳值(by value),傳址(by reference),輸出參數(by output),數組參數(by array)。傳值參數無需額外的修飾符,傳址參數需要修飾符ref,輸出參數需要修飾符out,數組參數需要修飾符params。傳值參數在方法調用過程中如果改變了參數的值,那麼傳入方法的參數在方法調用完成以後并不是以而改變,而是保留原來傳入時的值。傳址參數恰恰相反,如果方法調用過程改變了參數的值,那麼傳入方法的參數在調用完成以後也随之改變。實際上從名稱上我們可以清楚地看出兩者的含義--傳值參數傳遞的是調用參數的一份拷貝,而傳址參數傳遞的是調用參數的記憶體位址,該參數在方法内外指向的是同一個存儲位置。

轉載于:https://www.cnblogs.com/wangqc/p/ref_out_params.html

c#