傳值Call by Value / 傳址 Call by Reference
學過c++的一定會遇到傳值與傳址
一開始聽到整個
wtf 這兩個是尛阿
到最近看了一下ref跟out之後才真的了解
======
一般資料型別分為兩種
一個是實質型別
一個是參考型別
實質型別就是 int float char...等基礎的型別
而他變數記憶體存放的"內容"是值 所以稱為實"值"型別
也就是"傳值",當你在使用他的時候
他們之間傳遞的方式都是把值copy一份後再傳進去
像是以下
一開始宣告
int A=5, B=10;
並且設一個方法void ChangeValue(int a,int b)
{
a = 1;
b = 2;
}
之後在Start()方法內調用
Debug.Log(" A :" + A + " b :" + B); ChangeValue(A, B); Debug.Log(" A :" + A + " b :" + B);分別是將AB傳進去前跟傳進去後
可以看到傳進去後值都沒改變,這是因為使用的方式只是傳值(call by value)而已
意思就是把"值"複製給對方,而複製完改變的東西並不會影響到本身的值,因此不會做任何改變
而下面可以對照看看
Car car11 = new Car("car11");
Car car22 = new Car("car22");
void ChangeNewCarValue(Car _car11, Car _car22)
{
_car11._carName = "ChangeCAR11";
_car22._carName = "ChangeCAR22";
}
同樣的宣告 同樣的方法 同樣在Start內打上Debug.Log(" car11 :" + car11._carName + " car22 :" + car22._carName);
ChangeNewCarValue(car11, car22);
Debug.Log(" car11 :" + car11._carName + " car22 :" + car22._carName);
出來的結果則為結果卻改變了,因此從上可以推論出來Car是一個傳址Call by Reference
意思就是,它傳遞的不是複製一份出來的值,而是傳遞丟入物件的記憶體位址
然後間接透過它來操作物件,跟指標很類似。
其實在C/C++的時候 正確是有三個名詞的
call by value 傳值、call by reference 傳參考、call by address傳址
但由於這裡要講的是C#,所以用官方的翻譯來敘述 ->詳細點我
如果要詳細了解這三個有什麼差別 可以再去google
ref、out
ref 關鍵字會導致引數由參考加以傳遞,而非透過值。
參考程式碼 :
class RefExample
{
static void Method(ref int i)
{
// Rest the mouse pointer over i to verify that it is an int.
// The following statement would cause a compiler error if i
// were boxed as an object.
i = i + 44;
}
static void Main()
{
int val = 1;
Method(ref val);
Console.WriteLine(val);
// Output: 45
}
}
可以發現實質類型使用ref關鍵字之後,就會變得像是上面參考類型一樣
可以修改傳入的參數了
class RefExample
{
static void Method(ref int i)
{
// Rest the mouse pointer over i to verify that it is an int.
// The following statement would cause a compiler error if i
// were boxed as an object.
i = i + 44;
}
static void Main()
{
int val = 1;
Method(ref val);
Console.WriteLine(val);
// Output: 45
}
}
那問題來了,參考類型本身傳遞就可以直接修改值了
為何還會使用ref關鍵字加到參考型別身上呢?
1.明確提示
加了之後 不管給別人用還是自己用 都可以知道 傳入的參數是會被改變值得
不管傳入實質或參考都一樣
2.string的不變性
參考這裡
3. 為了修改默認值類型
ref重點:(msdn)
1.傳遞至 ref 參數的引數,在傳遞之前必須先初始化。
2.不能將ref和out用於async修飾詞定義的非同步方法。
3.有進有出
out關鍵字
基本上跟ref一樣
想要多個回傳值的時候,可以使用out
class OutReturnExample
{
static void Method(out int i, out string s1, out string s2)
{
i = 44;
s1 = "I've been returned";
s2 = null;
}
static void Main()
{
int value;
string str1, str2;
Method(out value, out str1, out str2);
// value is now 44
// str1 is now "I've been returned"
// str2 is (still) null;
}
}
ref跟out在使用上有很微小的差距
使用out的話,他不需要在被調用前初始化
但是調用者需要在返回之前指定輸出的參數
另一方面,可以用這樣去想
out類似於將方法附加返回值,也就是回傳多個值啦