mik*_*igs 5 c# encapsulation list
当为List属性(在C#中)实现setter时,编写它是一件坏事:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
set { _TheList = value; }
}
Run Code Online (Sandbox Code Playgroud)
它不应该写成:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
set { _TheList = new List<string>(value); }
}
Run Code Online (Sandbox Code Playgroud)
直到今天我通常使用前者,但我最近发现一些使用后者的代码,似乎这可能是实现它的正确方法.
当对分配给它的外部列表进行更改时,不使用前者会导致更改TheList属性.例如:
List<string> list = new List<string>();
list.Add("Hello");
var c = new someClass();
c.TheList = list;
Run Code Online (Sandbox Code Playgroud)
使用前者不会使用以下代码打破TheList的封装:
list.Clear();
Run Code Online (Sandbox Code Playgroud)
现在c.TheList也是空的,这可能不是我们想要的.但是,使用后一种方法,c .List不会被清除.
你的财产应该暴露一个Collection<T>,而不是一个List<T>.
编辑:解释:
如果其他代码复制对列表的引用(例如,var list = Thingy.TheList),如果将属性设置为其他列表,则可能会混乱.(它最终将持有一个孤儿)
通常,很少有理由允许人们将属性指向不同的集合实例.
使用Collection<T>而不是List<T>允许您拦截对集合的更改并添加验证或维护父字段.(通过继承Collection<T>和覆盖InsertItem以及其他方法)您甚至可以在shippinga库之后添加此类逻辑,而不会破坏调用代码.
我相信由于列表是参考对象,您需要做的就是获取参考.所以:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
}
Run Code Online (Sandbox Code Playgroud)
获得引用并对集合进行更改后,您将更改_TheList