C#方法 值传递 引用传递
一、核心前提调用方法传递参数时默认发生值传递值传递中值类型与引用类型的表现完全不同具体分两种情况单独说明值类型参数传递实参的值拷贝形参修改不影响实参引用类型参数传递实参的地址拷贝形参与实参指向同一对象引用传递需通过ref关键字显式声明并非默认传递方式二、值传递核心传递的是“拷贝”值拷贝/地址拷贝形参与实参本质相互独立引用类型除外指向同一对象分两种参数类型说明。一值传递值类型参数对应Test1方法1. 核心规则将实参的值拷贝一份赋值给形参方法体内修改形参的值不会影响调用时实参的值形参、实参相互独立2. 实战示例Test1// 调用代码 int a1 10; Test1(a1); // 实参a1的值10拷贝给形参a Console.WriteLine(a1的值是 a1); // 输出a1的值是10未被修改 // 方法定义值类型参数int public static void Test1(int a) { Console.WriteLine(a修改之前的值 a); // 输出10 a 20; // 修改形参a的值不影响实参a1 }二值传递引用类型参数对应Test2方法1. 核心规则将实参对象的内存地址拷贝一份赋值给形参形参和实参指向同一个内存地址本质是同一个对象两种修改方式及影响关键区分方式1通过对象.属性的方法修改 → 影响实参的对象值方式2通过new创建新对象改变形参指向 → 不影响实参的对象值2. 实战示例Test2// 前置准备自定义People类 public class People { public string Name { get; set; } } // 调用代码 People p1 new People() { Name 张三 }; Test2(p1); // 实参p1的地址拷贝给形参p Console.WriteLine(p1对象name值 p1.Name); // 输出李四被修改 // 方法定义引用类型参数People public static void Test2(People p) // 形参p与实参p1指向同一个对象 { Console.WriteLine(修改之前 p.Name); // 输出张三 // 方式1对象.属性修改影响实参 p.Name 李四; // 方式2new创建新对象不影响实参注释后不执行 // p new People() {Name李四 }; }三、引用传递ref关键字显式声明核心传递的是“同一引用”形参与实参完全绑定修改形参必影响实参分两种参数类型说明表现统一。一引用传递ref修饰值类型对应Test1方法1. 核心规则需用ref关键字同时修饰形参和实参调用时实参前必须加ref形参与实参指向同一个变量无拷贝完全绑定方法体内修改形参的值必然影响外部实参的值注意ref修饰的值类型参数调用前必须赋初始值否则报错2. 实战示例Test1// 引用传递:在方法内部修改形参值会影响到外部实参的值 // 调用代码 int a1 10; // ref参数必须赋初始值 Test1(ref a1); // 如果参数有ref关键字需要调用的时候实参前面添加ref关键字 Console.WriteLine(a的值为 a1); // 输出20实参被修改 // 方法定义ref修饰值类型参数int // ref:关键字的作用 把形参传值改成引用类型传值的形式通俗讲把方法内部形参和外部实参表示同一个 public static void Test1(ref int a) { a 20;// 此处修改会影响到外部a1值 }二引用传递ref修饰引用类型对应Test2方法1. 核心规则需用ref关键字同时修饰形参和实参调用时实参前必须加ref形参与实参指向同一个对象无地址拷贝完全绑定无论通过对象.属性修改还是new创建新对象都会影响外部实参2. 实战示例Test2// 验证参数是对象类型的时候前提参数使用ref关键字进行修饰不管对象.属性方式修改还是整体new对象方式修改 都会影响到实参 // 调用代码 People p1 new People() { Name 烧饼 }; Test2(ref p1); Console.WriteLine(p1.Name); // 对象.属性方式进行修改的话 这地方也会跟着变化武大郎 // 如果通过new修改整体对象 这地方也会跟着变化武大郎 // 方法定义ref修饰引用类型参数People // 传递People类型 public static void Test2(ref People a) { // 第一种修改 对象.属性进行 //a.Name 武大郎; // 第二种方式 通过new的方法修改整个对象 a new People() { Name 武大郎 }; }四、值传递与引用传递核心区别触发方式值传递默认触发引用传递需ref关键字显式声明传递内容值传递传“拷贝”值/地址引用传递传“同一引用”实参影响值传递值类型不影响引用类型改属性影响、new不影响引用传递无论类型修改必影响关键区分贴合代码总结值传递 在方法内部修改变量不会影响到外部如果对象.属性这种方式会影响到外部引用传递必须有ref 在方法内部修改变量会影响到外部五、高频易错点必避坑混淆值类型与引用类型的值传递误以为所有值传递都不影响实参引用类型通过属性修改会影响引用类型中new创建新对象后值传递不影响实参ref修饰的引用传递仍影响实参默认传递都是值传递并非引用类型默认是引用传递ref参数值类型未赋初始值就调用会报语法错误调用ref修饰的方法时实参前忘记加ref关键字会报语法错误六、核心总结值传递默认值类型传值拷贝不影响实参引用类型传地址拷贝改属性影响、new不影响引用传递ref显式声明、实参加ref形参与实参同一引用修改必影响实参所有类型适用ref值类型需初始化ref引用类型无论改属性还是new都影响实参核心区别值传递是“拷贝引用/值”引用传递是“共享同一引用”