如何将引用类型赋值给值类型(创建值类型副本)并保持数据独立
问题解答
一、让OtherName和OtherAge不受jane实例变更影响的方法
先帮你修正代码里的几个小语法问题:
- C#变量名区分大小写,
Jane要改成和实例名一致的jane - 类型名
Int得写成小写的int
修正后的代码如下:
string OtherName; int OtherAge; Person jane = new Person("Jane", 28); OtherName = jane.Name; OtherAge = jane.Age;
其实你现在的写法已经满足需求了,原因很简单:
int是值类型,赋值时会直接把jane.Age的数值(28)复制到OtherAge的内存空间里。之后哪怕你修改jane.Age = 30,OtherAge依然会保持28,完全不受原实例变更的影响。string虽然是引用类型,但它是不可变类型。赋值时复制的是"Jane"这个字符串的引用,但如果后续修改jane.Name = "Jane Smith",本质是创建了一个全新的字符串对象,jane.Name会指向这个新对象,而OtherName仍然指向原来的"Jane",所以也不会跟着变化。
要是你的Person类里有可变的引用类型成员(比如自定义的Address类),那就要考虑深拷贝,但针对当前的Name和Age,现有写法完全够用。
二、将引用类型转换为值类型(创建值类型副本)
首先要明确:引用类型和值类型属于不同的类型体系,不能直接把整个引用类型实例赋值给值类型变量,但你可以把引用类型的属性值复制到值类型中,或者定义一个对应的值类型结构体来存储引用类型的状态。
举个具体的例子,假设你想把Person这个引用类型实例转换成独立的值类型副本,可以这么做:
- 先定义一个值类型结构体(C#中结构体默认是值类型):
public struct PersonValue { public string Name { get; set; } public int Age { get; set; } // 从Person引用类型初始化值类型实例 public PersonValue(Person person) { Name = person.Name; Age = person.Age; } }
- 然后就可以把
jane这个引用类型实例转换成值类型副本:
Person jane = new Person("Jane", 28); PersonValue janeValue = new PersonValue(jane); // 后续修改原引用类型实例,值类型副本完全不受影响 jane.Age = 30; Console.WriteLine(jane.Age); // 输出30 Console.WriteLine(janeValue.Age); // 输出28
本质上就是把引用类型实例的各个值类型(或不可变引用类型)成员逐一复制到值类型实例中,这样就能得到一个独立的、不受原引用类型变更影响的值类型副本。
内容的提问来源于stack exchange,提问作者Mr. Henry
相关产品推荐
相关产品推荐

