
看起来没什么问题,对吧?Father没有提供setter,似乎是安全的。但是我们试试下面的代码。
static void Main(string[] args)
{
People father = new People(null) { Name = "father", Age = 60 };
People son = new People(father);
var f = son.Father;
f.Name="Changed";
son.ShowFather();
Console.ReadLine();
}

看,发现了什么,外部改变了本来应该被封装所保护的Father属性,封装被破坏了!
稍微一想我们应该能明白这个道理,Father属性返回的拷贝的变量和原Father变量指向同一块实例。要想解决这个问题,我们要么返回一个值类型,要么返回一个全新的对象。修改Father属性如下:
public People Father { get { return new People(_Father._Father) { Name = _Father.Name, Age = _Father.Age }; } }
再次测试,

这次封装就没问题了。
总结
我们大概知道了值类型和引用类型的区别,包括它们的行为,在内存的居住方式,以及使用引用类型时可能会遇到的暗坑,希望大家通过阅读这篇文章,能够加深一些对它们的了解,少走一些弯路。
今天也简单的提到了比较时的同一性,和预防封装被破坏所采用的返回一个新的实例拷贝的策略(这个时候适合使用DeepCopy),我们之后有机会再详细聊。
到此这篇关于c#中值类型和引用类型的文章就介绍到这了,更多相关c#值类型和引用类型内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!










