我有一个类,它定义了一个只读属性,可以有效地公开私有字段,如下所示:
public class Container
{
private List<int> _myList;
public List<int> MyList
{
get { return _myList;}
}
public Container() : base ()
{
_myList = new List<int>();
}
// some method that need to access _myList
public SomeMethod(int x)
{
_myList.Add(x);
}
}
现在消费者无法直接管理我的属性,所以代码如aContainer.MyList = new List();生成编译时错误。 但是,消费者可以完全自由地调用他所获得的各种方法,所以这是完全有效的代码
Container c = new Container();
Console.WriteLine(c.MyList.Count);
c.MyList.Add(4);
Console.WriteLine(c.MyList.Count);
哪种方式会破坏整个只读概念。
是否有任何合理的解决方法可以让我有一个真正的只读参考属性?
P.S。我不能只返回列表的副本,因为用户会认为他做了所有必要的更改,但唉......他们将会消失。
答案 0 :(得分:5)
不要直接引用您的列表。而是返回一个包裹它的ReadOnlyCollection,或者如果List&lt;&gt;返回类型设置为石头,返回列表的副本。他们可以做任何他们想要的副本而不影响原件。
答案 1 :(得分:2)
引用是"readonly",即实际对象。即你不能用另一个对象替换引用。所以,如果你有一个像这样打破它的类:
public class Container
{
private readonly List<int> _myList;
public List<int> MyList
{
get { return _myList;}
}
public Container() : base ()
{
_myList = new List<int>();
}
public void BreakReadOnly()
{
_myList = new List<int>();
}
}
...然后它甚至不会编译。这是因为readonly字段不能与任何其他对象重新分配。在这种情况下,BreakReadOnly
将尝试分配新列表。
如果你真的想要一个只读它的集合,那么你可以这样做:
public ReadOnlyCollection<int> MyList
{
get { return _myList.AsReadOnly(); }
}
希望这有帮助。
更新:删除了IEnumerable的使用。
答案 2 :(得分:2)
您可以像这样返回readonly Collection:
public ReadOnlyCollection<int> MyList
{
get { return _myList.AsReadOnly(); }
}
或返回一个新的List,以便调用者可以在不更改原始列表的情况下更改列表。
public List<int> MyList
{
get { return new List<int>(_myList)}
}
答案 3 :(得分:1)
查看静态Array.AsReadOnly()方法,您可以使用该方法返回数组周围的包装,以防止修改它。
答案 4 :(得分:0)
你想要_myList,它是一个只读的引用类型。嗯,它是readonly并且没有失败的readonly概念。
CLR为引用类型实现readonly属性,使得引用(如果需要,指向对象的指针)是readonly,而引用所指向的对象可以被修改。
要解决这个问题,你需要自己创建对象的成员字段,因为你不能通过将readonly标志附加到对象的引用来使整个对象只读。
您可以实现on immutable泛型集合类,其行为方式与List&lt;&gt;相同。对象,但只有成员。