列表属性设置器
当为 List 属性(在 C# 中)实现 setter 时,写成这样是不是一件坏事:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
set { _TheList = value; }
}
不应该写成:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
set { _TheList = new List<string>(value); }
}
直到今天我通常使用前者,但我最近发现一些使用后者的代码看起来这可能是实现这一点的正确方法。
当对分配给它的外部列表进行更改时,使用前者不会导致 TheList 属性发生更改。例如:
List<string> list = new List<string>();
list.Add("Hello");
var c = new someClass();
c.TheList = list;
使用前者不会破坏 TheList 的封装:
list.Clear();
现在 c.TheList 也是空的,这可能不是我们想要的。但是,使用后一种方法,c.TheList 将不会被清除。
When implementing a setter for a List property (in C#) is it a bad thing to write is as:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
set { _TheList = value; }
}
Should it not be written as:
private List<string> _TheList = new List<string>();
public List<string> TheList
{
get { return _TheList; }
set { _TheList = new List<string>(value); }
}
Up until today I have typically used the former, but I recently found some code that was using the latter and it seemed that this is probably the correct way to implement this.
Won't using the former cause the TheList property to be changed when changes are made to the external list that gets assigned to it. For example:
List<string> list = new List<string>();
list.Add("Hello");
var c = new someClass();
c.TheList = list;
Using the former won't the following code break the encapsulation of TheList:
list.Clear();
Now c.TheList is also empty, which may not be what we wanted. However, using the latter approach, c.TheList would not be cleared.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这完全取决于您希望您的财产如何运营。如果您想要副本,请制作副本。否则,不要。通常,这样的属性根本不会公开 setter,因为替换整个列表并不是这种情况下所需的操作。
当然,使用第二种方法可能会造成性能缺陷,因为属性语法隐藏了这样一个事实:每次使用 setter 时都会完全复制并创建一个新列表。
It completely depends on how you want your property to operate. If you want a copy, make a copy. Otherwise, don't. Often times properties like that won't expose a setter at all, since replacing the entire list isn't a desired action for that case.
Of course, using your second method is potentially a performance pitfall, since the property syntax hides the fact that you're completely copying and creating a new list every time you use the setter.
首先,两者都有些不正确。公共属性确实应该公开为 IList,因为 List 是特定于实现的(当使用 List 作为公共属性时,fxcop 实际上会警告您)。
其次,如果可能的话,我会让设置器是私有的。使用 getter,用户仍然可以添加/删除/清除等。但简化了您在问题中提出的问题。
First off, both are somewhat incorrect. Public properties should really be exposed as IList since List is implementation specific (fxcop will actually warn you when using List as a public property).
Second, if possible I would have the setter be private. Using the getter a user can still Add/Remove/Clear/etc. but simplifies the issues you raised in your question.
我认为你的问题没有一个普遍的答案。您所描述的行为可能是您想要的,也可能不是您想要的。
总的来说,我同意 SLAks 的观点,即保持集合属性只读会更干净,但这一切都取决于
I do not think there is a universal answer to your question. The behavior you describe may or may not be what you want.
In general I agree with SLaks that it is cleaner to keep the collections properties read-only but it all depends
我不确定我理解是否正确。但我是这样做的:
I am not sure I understood correctly. But i am doing it like that:
集合属性应为只读。
您的属性应公开
Collection
,而不是列表
。编辑:说明:
如果其他代码复制对列表的引用(例如,
var list = Thingy.TheList
),如果将该属性设置为不同的列表。 (它最终会抱着一个孤儿)一般来说,很少有理由允许人们将属性指向不同的集合实例。
使用
Collection
而不是List
允许您拦截对集合的更改并添加验证或维护父字段。 (通过继承Collection
并重写InsertItem
和其他方法)您甚至可以在发布库后添加此类逻辑,而不会破坏调用代码。Collection properties should be readonly.
Your property should expose a
Collection<T>
, not aList<T>
.EDIT: Explanations:
If other code copies a reference to the list (eg,
var list = Thingy.TheList
), it can get messed up if you set the property to a different list. (It will end up holding an orphan)In general, there are very few reasons to allow people to make a property point to a different collection instance.
Using
Collection<T>
instead ofList<T>
allows you to intercept changes to the collection and add validation or maintain parent fields. (by inheritingCollection<T>
and overridingInsertItem
and other methods) You can even add such logic after shippinga library without breaking calling code.我相信由于列表是一个引用对象,因此您所需要做的就是获取引用。所以:
一旦你有了引用,并对集合进行了更改,你就改变了 _TheList
I believe since a list is a reference object, all you need to do is get the reference. So:
Once you have the reference, and make changes to the collection, you're changing _TheList