C# 最佳实践:如何公开只读ICollection
我的类中有一个名为C# 最佳实践:如何公开只读ICollection,c#,collections,c#-2.0,C#,Collections,C# 2.0,我的类中有一个名为foos的ICollection,我想以只读形式公开(请参阅)。我看到接口定义了一个属性.IsReadOnly,这似乎是合适的。。。我的问题是:如何让类的消费者清楚地知道foos是只读的 我不想依靠他们在尝试未实现的方法(如.Add())之前记住查询.IsReadOnly)。理想情况下,我希望将foos公开为ReadOnlyCollection,但它不实现IList。我是否应该通过一个名为GetReadOnlyFooCollection的方法而不是通过属性公开foo?如果是这样
foos
的ICollection
,我想以只读形式公开(请参阅)。我看到接口定义了一个属性.IsReadOnly
,这似乎是合适的。。。我的问题是:如何让类的消费者清楚地知道foos
是只读的
我不想依靠他们在尝试未实现的方法(如.Add()
)之前记住查询.IsReadOnly
)。理想情况下,我希望将foos
公开为ReadOnlyCollection
,但它不实现IList
。我是否应该通过一个名为GetReadOnlyFooCollection
的方法而不是通过属性公开foo
?如果是这样的话,这会不会让那些期待ReadOnlyCollection
的人感到困惑
这是C#2.0,因此像ToList()
这样的扩展方法不可用…您可以使“foos”成为如下的只读集合:
ReadOnlyCollection<T> readOnlyCollection = foos.ToList<T>().AsReadOnly();
ReadOnlyCollection ReadOnlyCollection=foos.ToList().AsReadOnly();
然后可以将其作为类的属性公开
编辑:
class容器
{
私人ICollection foos;
public ReadOnlyCollection ReadOnlyFoos{get{return foos.ToList().AsReadOnly();}
}
注意:您应该记住,一旦获得ReadOnlyFoos集合,它就不再与您的foos ICollection“同步”。请参阅。我的建议是返回并直接为场景使用ReadOnlyCollection。这使得使用对调用用户是明确的 通常我会建议使用适当的接口。但是,鉴于.NET Framework当前没有合适的IReadOnlyCollection,您必须使用ReadOnlyCollection类型 另外,在使用ReadOnlyCollection时必须注意,因为它实际上不是只读的:返回一个T[]:
private ICollection<T> items;
public T[] Items
{
get { return new List<T>(items).ToArray(); }
}
私有i收集项目;
公共T[]项目
{
获取{返回新列表(项).ToArray();}
}
有时您可能希望使用接口,可能是因为您希望在单元测试期间模拟集合。请参阅my,了解如何使用适配器将自己的接口添加到ReadonlyCollection。我通常返回一个IEnumerable
一旦您将集合设置为只读(因此像Add
、Remove
和Clear
这样的方法不再有效),集合支持的可枚举项就不多了——我相信,只需计数
和包含
如果类的使用者真的需要像对待集合中的元素一样对待元素,那么将
IEnumerable
传递给List
的构造函数就很容易了。我似乎已经决定在克隆对象的情况下返回IEnumerable。
public IEnumerable<Foose> GetFooseList() {
foreach(var foos in Collection) {
yield return foos.Clone();
}
}
public IEnumerable GetFooseList(){
foreach(集合中的var foos){
产生返回foos.Clone();
}
}
- 在Foos上需要克隆方法
这不允许在集合中进行任何更改。请记住,ReadonlyCollection是“泄漏的”,因为它内部的对象可以按照另一篇文章中的链接所述进行更改。自从问题被写出来后,.NET 4.0添加了一个
IReadOnlyCollection
接口;最好使用它作为声明的返回类型
然而,这就留下了一个悬而未决的问题,即返回什么类型的实例。一种方法是克隆原始集合中的所有项目。另一种方法是始终返回只读包装。第三种方法是,如果实现了IReadOnlyCollection
,则返回原始集合。在某些情况下,每种方法都是最好的,但在其他情况下则不太理想(或者完全可怕)。不幸的是,Microsoft没有提供标准的方法来提问两个非常重要的问题:
public IEnumerable<Foose> GetFooseList() {
foreach(var foos in Collection) {
yield return foos.Clone();
}
}