【C#】C#中值类型和引用类型参数传递的区别

C#中值类型和引用类型参数传递的区别

1. C#中的参数传递机制

在C#中,参数传递主要分为两种情况:

  • 值类型传递 :传递的是变量的副本,方法内的修改不会影响原始变量。
  • 引用类型传递 :传递的是对象引用的副本,方法内对对象属性的修改会影响原始对象。

普通函数参数传递的区别主要取决于参数的类型:

  • 如果参数是值类型 (如int、struct等):方法内的修改不会影响原始变量。
  • 如果参数是引用类型 (如class、interface等):方法内对对象属性的修改会影响原始对象。

示例

csharp 复制代码
using System;

namespace ParamPassingDemo
{
    // 引用类型(类)
    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public override string ToString()
        {
            return $"Person{{Name='{Name}', Age={Age}}}";
        }
    }

    // 值类型(结构体)
    struct Point
    {
        public int X { get; set; }
        public int Y { get; set; }

        public override string ToString()
        {
            return $"Point{{X={X}, Y={Y}}}";
        }
    }

    class Program
    {
        // 修改引用类型参数的方法
        static void ModifyPerson(Person person)
        {
            // 直接修改引用指向的对象的属性
            person.Name = "Modified Alice";
            person.Age = 30;
            
            Console.WriteLine($"ModifyPerson方法内: {person}");
        }

        // 修改值类型参数的方法
        static void ModifyPoint(Point point)
        {
            // 修改的是副本的属性
            point.X = 100;
            point.Y = 200;
            
            Console.WriteLine($"ModifyPoint方法内: {point}");
        }

        // 创建新对象并赋值给引用参数
        static void ReplacePerson(Person person)
        {
            // 创建新对象并赋值给参数(修改的是参数指向的引用)
            person = new Person { Name = "New Person", Age = 40 };
            
            Console.WriteLine($"ReplacePerson方法内: {person}");
        }

        // 使用ref关键字传递值类型
        static void ModifyPointRef(ref Point point)
        {
            // 修改的是原始对象的属性
            point.X = 100;
            point.Y = 200;
            
            Console.WriteLine($"ModifyPointRef方法内: {point}");
        }

        static void Main(string[] args)
        {
            Console.WriteLine("=== C# 参数传递演示 ===");
            Console.WriteLine();

            // 1. 引用类型参数传递
            Console.WriteLine("1. 引用类型(类)参数传递:");
            Person alice = new Person { Name = "Alice", Age = 25 };
            Console.WriteLine($"调用前: {alice}");
            ModifyPerson(alice);
            Console.WriteLine($"调用后: {alice}");
            Console.WriteLine("结论: 引用类型参数传递时,方法内对对象的修改会影响原始对象");
            Console.WriteLine();

            // 2. 值类型参数传递
            Console.WriteLine("2. 值类型(结构体)参数传递:");
            Point p1 = new Point { X = 10, Y = 20 };
            Console.WriteLine($"调用前: {p1}");
            ModifyPoint(p1);
            Console.WriteLine($"调用后: {p1}");
            Console.WriteLine("结论: 值类型参数传递时,方法内的修改不会影响原始对象");
            Console.WriteLine();

            // 3. 替换引用类型参数指向的对象
            Console.WriteLine("3. 替换引用类型参数指向的对象:");
            Person bob = new Person { Name = "Bob", Age = 35 };
            Console.WriteLine($"调用前: {bob}");
            ReplacePerson(bob);
            Console.WriteLine($"调用后: {bob}");
            Console.WriteLine("结论: 替换参数指向的引用不会影响原始对象");
            Console.WriteLine();

            // 4. 使用ref关键字传递值类型
            Console.WriteLine("4. 使用ref关键字传递值类型:");
            Point p2 = new Point { X = 50, Y = 60 };
            Console.WriteLine($"调用前: {p2}");
            ModifyPointRef(ref p2);
            Console.WriteLine($"调用后: {p2}");
            Console.WriteLine("结论: 使用ref关键字可以让方法修改原始值类型对象");
            Console.WriteLine();

            Console.WriteLine("=== 总结 ===");
            Console.WriteLine("1. 值类型: 默认传递副本,方法内修改不影响原始对象");
            Console.WriteLine("2. 引用类型: 默认传递引用的副本,方法内修改对象属性会影响原始对象");
            Console.WriteLine("3. 替换引用: 修改参数指向的引用不会影响原始对象");
            Console.WriteLine("4. ref关键字: 可以让方法直接修改原始参数");
        }
    }
}

运行结果

bash 复制代码
=== C# 参数传递演示 ===

1. 引用类型(类)参数传递:
调用前: Person{Name='Alice', Age=25}
ModifyPerson方法内: Person{Name='Modified Alice', Age=30}
调用后: Person{Name='Modified Alice', Age=30}
结论: 引用类型参数传递时,方法内对对象的修改会影响原始对象

2. 值类型(结构体)参数传递:
调用前: Point{X=10, Y=20}
ModifyPoint方法内: Point{X=100, Y=200}
调用后: Point{X=10, Y=20}
结论: 值类型参数传递时,方法内的修改不会影响原始对象

3. 替换引用类型参数指向的对象:
调用前: Person{Name='Bob', Age=35}
ReplacePerson方法内: Person{Name='New Person', Age=40}
调用后: Person{Name='Bob', Age=35}
结论: 替换参数指向的引用不会影响原始对象

4. 使用ref关键字传递值类型:
调用前: Point{X=50, Y=60}
ModifyPointRef方法内: Point{X=100, Y=200}
调用后: Point{X=100, Y=200}
结论: 使用ref关键字可以让方法修改原始值类型对象

=== 总结 ===
1. 值类型: 默认传递副本,方法内修改不影响原始对象
2. 引用类型: 默认传递引用的副本,方法内修改对象属性会影响原始对象
3. 替换引用: 修改参数指向的引用不会影响原始对象
4. ref关键字: 可以让方法直接修改原始参数
相关推荐
virus594520 小时前
悟空CRM mybatis-3.5.3-mapper.dtd错误解决方案
java·开发语言·mybatis
初次见面我叫泰隆20 小时前
Qt——3、常用控件
开发语言·qt·客户端
无小道21 小时前
Qt——QWidget
开发语言·qt
时艰.21 小时前
Java 并发编程之 CAS 与 Atomic 原子操作类
java·开发语言
梵刹古音1 天前
【C语言】 函数基础与定义
c语言·开发语言·算法
梵刹古音1 天前
【C语言】 结构化编程与选择结构
c语言·开发语言·嵌入式
Yvonne爱编码1 天前
JAVA数据结构 DAY3-List接口
java·开发语言·windows·python
一方_self1 天前
了解和使用python的click命令行cli工具
开发语言·python
南宫码农1 天前
我的电视 - Android原生电视直播软件 完整使用教程
android·开发语言·windows·电视盒子
CoderCodingNo1 天前
【GESP】C++四级/五级练习题 luogu-P1223 排队接水
开发语言·c++·算法