会共享。c#中的结构体是值类型,赋值或传递时执行的是浅拷贝(shallow copy),即字段被逐个复制。如果结构体中包含引用类型字段(如类、数组、字符串等),复制后的新结构体中的该字段将指向原对象在堆上的同一内存地址,因此修改其中一个结构体里的引用类型字段内容,另一个也会受到影响。

结构体赋值时的内存布局变化
当使用 `=` 运算符将一个结构体实例赋值给另一个结构体实例时,CLR 会在栈上为新的结构体分配空间,并将源结构体的所有字段值按位复制到目标结构体中。对于值类型字段(如 `int`, `double`),这是完全独立的副本;但对于引用类型字段,复制的仅仅是“引用”本身(即内存地址指针),而不是引用所指向的对象实体。

using System;
public struct PersonRecord
{
public string Name; // 引用类型
public int Age; // 值类型
}
class Program
{
static void Main()
{
// 初始化原始结构体
PersonRecord original = new PersonRecord();
original.Name = "Alice";
original.Age = 30;
// 执行浅拷贝
PersonRecord copy = original;
// 修改副本中的引用类型字段
copy.Name = "Bob";
// 验证结果
Console.WriteLine($"Original: {original.Name}, {original.Age}");
Console.WriteLine($"Copy: {copy.Name}, {copy.Age}");
}
}预期输出:
Original: Alice, 30
Copy: Bob, 30
结构体作为参数传递时的行为
在 C# 中,结构体作为方法参数传递时,默认也是按值传递(pass-by-value)。这意味着调用方法时,实参结构体的完整副本会被压入栈中传递给形参。如果在方法内部修改了该结构体的值类型字段,不会影响外部原始结构体;但如果修改了引用类型字段的内容(例如修改了字符串引用的对象,虽然字符串不可变,但如果是 List

using System;
using System.Collections.Generic;
public struct Container
{
public List<string> Items; // 引用类型
public int Count; // 值类型
}
class Program
{
static void ProcessData(Container c)
{
// 修改引用类型字段的内容
c.Items.Add("Item1");
// 修改值类型字段
c.Count = 100;
}
static void Main()
{
Container myContainer = new Container();
myContainer.Items = new List<string>();
myContainer.Count = 0;
ProcessData(myContainer);
Console.WriteLine($"Count: {myContainer.Count}");
Console.WriteLine($"Items Count: {myContainer.Items.Count}");
}
}预期输出:
Count: 0
Items Count: 1
如何避免结构体中引用类型的共享问题
如果需要结构体在复制后拥有独立的引用类型数据,必须手动实现深拷贝(Deep Copy)。这通常通过实现 `ICloneable` 接口或在属性/方法中创建新的引用类型实例来完成。另一种现代做法是使用 `record struct`(C# 10+),它提供了基于值的相等性比较,但在默认情况下仍然执行浅拷贝,除非显式定义克隆逻辑。最安全的策略是在结构体设计阶段尽量避免包含复杂的可变引用类型字段,或者确保这些引用类型是不可变的(如 `string`)。


















