值類型傳參
- 默認按值傳遞:在棧上拷貝數據副本,方法內修改不影響原變量。
ref / out:傳遞地址,方法內修改直接影響原變量。
引用類型傳參
- 默認按值傳遞引用:拷貝引用(指針),方法內修改對象內容影響原對象,但重新賦值參數(
param = new Obj())不影響原變量。
ref:傳遞引用的地址,方法內param = new Obj()會改變原變量指向。
代碼對比
// 值類型
void Val(int x) { x = 10; }
void RefVal(ref int x) { x = 10; }
int a = 5; Val(a); // a=5
int b = 5; RefVal(ref b); // b=10
// 引用類型
class MyInt { public int Val; }
void Ref(MyInt m) { m.Val = 10; } // 修改內容
void RefReassign(MyInt m) { m = new MyInt { Val = 20 }; } // 重新賦值參數
void RefRef(ref MyInt m) { m = new MyInt { Val = 30 }; } // ref 重新賦值
MyInt o1 = new MyInt { Val = 1 };
Ref(o1); // o1.Val = 10
RefReassign(o1); // o1.Val = 10 (未變)
RefRef(ref o1); // o1 指向新對象,Val = 30
大結構體傳參優化
struct BigStruct { public long A,B,C,D,E,F,G,H,I,J; } // 80 字節
void ByVal(BigStruct s) { } // 每次調用拷貝 80 字節
void ByRef(ref BigStruct s) { } // 僅傳遞 8 字節指針
// 高頻調用場景強烈建議使用 ref
ref 返回值與局部變量
ref int Find(int[] arr, int target)
{
for (int i = 0; i < arr.Length; i++)
if (arr[i] == target) return ref arr[i];
throw new Exception();
}
// 使用
int[] a = {1,2,3};
ref int r = ref Find(a, 2);
r = 20; // a[1] = 20
總結表