说我有:
class foo
{
private List<T> bar;
public IEnumerable<T> GetBar();
}
其中GetBar()
应该返回相同的List,而不暴露内部(即没有其他类应该能够从内部列表中删除元素,重新排序等)并避免过度复制。这样做的标准方法是什么?
答案 0 :(得分:8)
如果要返回不可变列表,请返回bar.AsReadOnly()
。
通常,公开此只读包装器的成员的类型为IList<T>
。如果我想向消费者表明实现可能使用延迟枚举,我只会转发到IEnumerable<T>
。
我个人认为它是一个属性,并在每次调用时返回相同的只读包装:
class Foo
{
private List<T> bar;
private IList<T> readonlyBar;
public Foo()
{
bar = ...;
readonlyBar = bar.AsReadOnly();
}
public IList<T> Bar
{
get { return readonlyBar; }
}
}
答案 1 :(得分:7)
您可以从方法中返回ReadOnlyCollection的实例:
return new ReadOnlyCollection(items);
答案 2 :(得分:0)
如果类型是可变类,则封装对象的可变状态的一部分的属性可以表示以下任何一个:
如果类型是只读的,但不保证是不可变的,则可能代表以下任何一种:
虽然确定对象的类型可用于区分第一组三个行为与后一个集合,但我知道在没有合适的保证不可变返回类型的情况下没有标准约定来指示适当的集合中的行为适用。由于IEnumerable<T>
没有保证不可变的实现,这似乎适用于此,您最好的选择可能是使用Joe的代码,但也将您的行为记录为#3。除非您能够想到客户会从#2中受益的某些原因,否则将您的行为记录为#3将为您提供最大的灵活性,以便在将来有必要时更改您的实施。例如,如果将来最终需要线程安全访问,那么您的类可以实现一个内部方法,该方法将集合锁定足够长的时间以将其复制到数组并返回该数组(可能包含在ReadOnlyCollection<T>
中,尽管它可能无关紧要)演员为IEnumerable<T>
。如果该属性应该代表实时视图,那么这种方法将不起作用。