C# 列表属性设置器

C# 列表属性设置器,c#,list,encapsulation,C#,List,Encapsulation,在实现列表属性的setter(在C#中)时,编写如下内容是否是一件坏事: private List<string> _TheList = new List<string>(); public List<string> TheList { get { return _TheList; } set { _TheList = value; } } 现在c.列表也是空的,这可能不是我们想要的。但是,使用

在实现列表属性的setter(在C#中)时,编写如下内容是否是一件坏事:

    private List<string> _TheList = new List<string>();
    public List<string> TheList
    {
        get { return _TheList; }
        set { _TheList = value; }
    }
现在c.列表也是空的,这可能不是我们想要的。但是,使用后一种方法,c.t列表不会被清除。

编辑:说明:

如果其他代码复制了对列表的引用(例如,
var list=Thingy.TheList
),那么如果将属性设置为其他列表,则可能会弄糟。(最终将收容一名孤儿)
通常,很少有理由允许人们将属性指向不同的集合实例


使用
集合
而不是
列表
可以拦截对集合的更改,并添加验证或维护父字段。(通过继承
集合
并重写
插入项
和其他方法),您甚至可以在交付库后添加此类逻辑,而无需中断调用代码。

这完全取决于您希望属性如何操作。如果你想要一份,就复印一份。否则,不要。通常情况下,这样的属性根本不会公开setter,因为替换整个列表并不是这种情况下需要的操作


当然,使用第二种方法可能会造成性能缺陷,因为属性语法隐藏了这样一个事实:每次使用setter时,您都在完全复制和创建一个新列表。

首先,这两种方法都有点不正确。公共属性实际上应该作为IList公开,因为列表是特定于实现的(当使用列表作为公共属性时,fxcop实际上会警告您)


第二,如果可能的话,我会让二传手保密。使用getter,用户仍然可以添加/删除/清除/等,但可以简化您在问题中提出的问题。

我认为,由于列表是一个引用对象,所以您只需获取引用即可。因此:

   private List<string> _TheList = new List<string>();
public List<string> TheList
{
    get { return _TheList; }
}
private List\u TheList=new List();
公开名单
{
获取{return\u TheList;}
}

一旦你有了参考资料,并对收藏进行了更改,你就是在更改列表。我认为你的问题没有一个通用的答案。你描述的行为可能不是你想要的


总的来说,我同意SLaks的观点,即将collections属性保持为只读比较干净,但这一切都取决于

我不确定我是否理解正确。但我是这样做的:

c.TheList = list.ToArray().ToList(); 

不,第二种解决方案不正确。使用第一种解决方案,如果您想设置一个副本而不是一个引用-写c.TheList=newlist(List);这取决于您的所有权语义。一些呼叫者可能希望能够设置列表,并且仍然“从外部”更新列表。无论你走哪条路,一定要把它适当地记录下来。谢谢你所有的好答案。我很高兴我没有在没有先检查的情况下开始使用第二种方法。似乎大家的共识是不提供setter(在大多数情况下)或至少使其受到保护。或者公开为
ReadOnlyCollection
List
有一个AsReadOnly()方法来简化返回。你知道有什么好文章解释这两个原则成立的原因吗?我不完全明白将可写列表作为属性有什么不对。很棒的链接!我以前从未使用过任何代码分析工具。这和安装/运行fxCop一样简单吗?坦率地说,我很害怕在我正在从事的当前项目上运行fxCop:P@What:是的。请注意,当第一次在一个非平凡的现有项目上运行时,它会给出成百上千的警告。@SLaks我知道这篇文章有点旧,但我想知道从IList继承是否合适。IList直接从ICollection、IEnumerable和IEnumerable继承。我计划使用WCF进行序列化,因此继承虽然在OO层很重要,但需要在消息传递层进行扁平化以保持性能。不管怎样,使用IList是否有任何问题?我会假设,在这种情况下,人们不会编写自己的所有方法功能。IList似乎简化了继承引用。我通常会使用IList,但由于在第二种方法中,我们显式地使用new List(),因此我认为这样定义属性更有意义。我刚刚意识到IList不包括我想要的AddRange方法。只有列表实现包含此方法。那么,为什么我不将这个属性公开为一个列表呢?那么,您有一个列表,可以将其转换为数组,然后再转换回列表?正如许多评论者已经同意的那样,您通常不希望通过setter公开列表,为了实现您的提议,您必须使用setter。你能解释一下你在这里的提议吗。
list.Clear();
   private List<string> _TheList = new List<string>();
public List<string> TheList
{
    get { return _TheList; }
}
c.TheList = list.ToArray().ToList();