当返回仅仅是一个私有成员的对象引用时,我们应该如何防御?在某种程度上
本文关键字:我们 对象引用 在某种程度上 何防御 成员 仅仅是 返回 一个 | 更新日期: 2023-09-27 18:05:07
考虑这个c#程序:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SandboxApplication
{
public class IntsOwner
{
private List<int> _ints;
public IntsOwner (IEnumerable<int> ints)
{
_ints = ints.OrderBy(i => i).ToList(); // They must be in the correct order
}
public IEnumerable<int> Ints
=> _ints;
public void CheckFirstTwoInts ()
{
if (_ints.Count < 2)
{
Console.WriteLine("You need to collect some more ints before trying this.");
}
else if (_ints[0] <= _ints[1])
{
Console.WriteLine("Your ints are in the correct order and you should stop worrying.");
}
else
{
Console.WriteLine("You've failed, your highness.");
}
}
}
class Program
{
static void Main (string[] args)
{
var intsOwner = new IntsOwner(new List<int> {1, 2, 3, 4, 5});
var ienumerable = intsOwner.Ints;
var list = (List<int>)ienumerable;
intsOwner.CheckFirstTwoInts();
list[0] = 6;
intsOwner.CheckFirstTwoInts();
Console.ReadLine();
}
}
}
如果运行此命令,您将得到两行输出:
Your ints are in the correct order and you should stop worrying.
You've failed, your highness.
IntsOwner
类的原始设计者想要确保私有成员_ints
拥有一个特定的属性(列表元素的排序)。但是,由于对实际对象的引用是通过Ints
属性返回的,因此该类的用户可以修改对象,使该属性不再有效。
这类代码在实践中不太可能出现,但是对私有成员的控制以这种方式"泄漏"仍然令人不安。程序员应该在多大程度上阻止这种事情的发生?例如,将Ints
属性的表达式体更改为_ints.Select(i = i)
,从而关闭这种修改私有成员的方式是否合理或相称?或者这会是不必要的偏执,损害代码的可读性吗?
我总是在ToList后面添加一个AsReadOnly()调用
在返回类型
中,不变性是关键,而不仅仅是最小知识原则https://msdn.microsoft.com/en-us/library/e78dcd75 (v = vs.110) . aspx
你可以这样做
public IEnumerable<int> Ints => _ints.ToList<int>();
所以你没有返回对_intts的引用,而只是一个复制的列表。任何修改返回值的人都只是在修改他们自己的副本,而不是私有存储的副本。