找回密码
 register

QQ登录

只需一步,快速开始

查看: 20|回复: 0

[*编程基础*] C# 中的值类型(Value Type)和引用类型(Reference Type)详解

[复制链接]

[*编程基础*] C# 中的值类型(Value Type)和引用类型(Reference Type)详解

[复制链接]
  • 打卡等级:热心大叔
  • 打卡总天数:165
  • 打卡月天数:14
  • 打卡总奖励:163
  • 最近打卡:2025-04-18 14:16:51
Waylee

主题

0

回帖

1万

积分

仙帝

积分
19287
Waylee 2025-4-15 18:21 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?register

×

在 C# 中,数据类型分为 值类型(Value Type) 和 引用类型(Reference Type),它们在内存管理、赋值行为和存储方式上有本质区别。


1. 值类型 vs. 引用类型:核心区别

特性 值类型(Value Type) 引用类型(Reference Type)
存储位置 通常存储在 栈(Stack) 通常存储在 堆(Heap)
赋值行为 复制数据本身(独立副本) 复制引用(指向同一对象)
修改影响 修改一个变量不影响另一个 修改一个变量会影响所有引用该对象的变量
示例类型 int, float, bool, struct class, string, array, delegate

2. 代码示例分析

using System;

namespace ConsoleApp1 
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ReAndValue.Demo();
        }
    }
    class Stamp 
    {
        public int Age { get; set; }
        public string Name { get; set; }
    }

    static class ReAndValue 
    {
        public static void Demo()
        {
            // 创建两个独立的对象 
            Stamp stamp1 = new Stamp { Age = 29, Name = "John" };
            Stamp stamp2 = new Stamp { Age = 30, Name = "Mary" };

            // 值类型赋值(复制数据)
            int age = stamp1.Age;  // age = 29(独立副本)
            stamp1.Age = 80;       // 修改 stamp1.Age 不影响 age 
            Console.WriteLine($"stamp1.Age = {stamp1.Age}");  // 80 
            Console.WriteLine($"age = {age}");                // 29 

            // 引用类型赋值(复制引用)
            Stamp stamp3 = stamp2;  // stamp3 和 stamp2 指向同一个对象 
            stamp2.Name = "Tom";    // 修改 stamp2 会影响 stamp3 
            Console.WriteLine($"stamp2.Name = {stamp2.Name}");  // Tom 
            Console.WriteLine($"stamp3.Name = {stamp3.Name}");  // Tom 
        }
    }
}

关键点解析

  1. 值类型赋值int age = stamp1.Age

    • agestamp1.Age 的 独立副本,修改 stamp1.Age 不会影响 age
    • 适用于需要数据隔离的场景(如临时变量、简单计算)。
  2. 引用类型赋值Stamp stamp3 = stamp2

    • stamp3stamp2 指向同一个对象,修改其中一个会影响另一个。
    • 适用于需要共享数据的场景(如对象传递、集合操作)。

3. 深入理解内存分配

(1) 值类型(栈存储)

  • 存储在栈(Stack),分配和回收速度快。
  • 每个变量拥有独立的内存空间。
  • 示例:
    int a = 10;  // 栈上分配 
    int b = a;   // 复制值,b 和 a 独立 

(2) 引用类型(堆存储)

  • 存储在堆(Heap),变量存储的是 引用地址(类似指针)。
  • 多个变量可以指向同一个对象。
  • 示例:
    Stamp s1 = new Stamp();  // 堆上分配对象 
    Stamp s2 = s1;           // s2 和 s1 指向同一对象 

4. 常见问题 & 注意事项

(1) string 是引用类型,但行为类似值类型

  • string 虽然是引用类型,但它是 不可变(Immutable) 的,修改时会创建新对象:
    string s1 = "Hello";
    string s2 = s1;  // s2 指向 "Hello"
    s1 = "World";    // s1 指向新对象 "World",s2 仍指向 "Hello"

(2) struct(结构体)是值类型,class 是引用类型

  • struct 适合小型、不可变的数据结构(如坐标 Point)。
  • class 适合复杂对象(如 PersonOrder)。

(3) 装箱(Boxing)和拆箱(Unboxing)

  • 装箱:值类型 → 引用类型(object
    int num = 10;
    object obj = num;  // 装箱(堆上分配)
  • 拆箱:引用类型 → 值类型
    int num2 = (int)obj;  // 拆箱(可能抛出异常)
  • 频繁装箱/拆箱会影响性能,应尽量避免。

5. 如何选择值类型 vs. 引用类型?

场景 推荐类型
小型、不可变数据(如坐标、日期) struct(值类型)
需要共享修改的对象(如用户信息) class(引用类型)
高性能计算(避免堆分配) 值类型
复杂对象(继承、多态) 引用类型

6. 总结

  • 值类型:数据独立,修改不影响其他变量,适合简单数据。
  • 引用类型:共享数据,修改会影响所有引用,适合复杂对象。
  • 理解两者的区别能帮助你:
    • 避免意外的数据修改(如引用类型误用)。
    • 优化内存使用(减少不必要的堆分配)。

您需要登录后才可以回帖 登录 | register

本版积分规则

雪舞知识库 | 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 |天天打卡

GMT+8, 2025-4-19 07:48 , Processed in 0.111940 second(s), 6 queries , Redis On.

Powered by XueWu Licensed

Copyright © Tencent Cloud.

快速回复 返回顶部 返回列表