【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关键字: 可以让方法直接修改原始参数
相关推荐
Data_agent2 小时前
实战:用Splash搞定JavaScript密集型网页渲染
开发语言·javascript·ecmascript
leiming62 小时前
C++ 02 函数模板案例
开发语言·c++·算法
weixin_421585012 小时前
PYTHON 迭代器1 - PEP-255
开发语言·python
小新1102 小时前
vs2022+Qt插件初体验,创建带 UI 界面的 Qt 项目
开发语言·qt·ui
摘星编程2 小时前
Ascend C编程语言详解:打造高效AI算子的利器
c语言·开发语言·人工智能
雨中飘荡的记忆3 小时前
Java面向对象编程详解
java·开发语言
用户8356290780513 小时前
使用 C# 高效解析 PDF 文档:文本与表格提取实战指南
后端·c#
222you3 小时前
线程的常用方法
java·开发语言
rit84324993 小时前
C#实现的远程控制系统
前端·javascript·c#