好的,所以 List<> 包含 AsReadOnly(),它为您提供 ReadOnlyCollection。我需要的是有一个 IList 类型的字段,以及一个将为该列表返回 ReadOnlyCollection 的属性。
示例类:
class Test
{
private IList<Abc> list;
public AddToList(Abc someItem) { /* adds inside the list */... }
public ReadOnlyCollection<Abc> List { get { return ??? } } // <- no "set" here!
}
场景如下:当将项目添加到列表中时,我需要在类中添加一些自定义逻辑,并且我想通过调用 AddToList(someitem) 来限制添加到此列表,同时不允许使用 list.Add (某些项目)。问题是我使用 NHibernate 需要 IList 接口,所以我无法在 IList 上强制转换/调用 AsReadOnly() (它不包含此方法)。
您建议采取什么方法来解决这种情况?我只需要一种让 NHibernate 以某种方式设置所需集合的方法,但我还需要限制用户。
你可以模仿
AsReadOnly()
:
public ReadOnlyCollection<Abc> List
{
get { return new ReadOnlyCollection<Abc>(list); }
}
更新:
这不会创建
list
的副本。 ReadOnlyCollection
不复制数据,它直接在提供的列表上工作。请参阅文档:
只读集合只是带有防止修改集合的包装器的集合;因此,如果对基础集合进行更改,只读集合会反映这些更改。
这个构造函数是一个 O(1) 操作。
尝试
return new ReadOnlyCollection<Abc> (list);
使用以下方式,
public class Test
{
private IList<SubTest> _subTests;
public virtual void AddSubTest(SubTest SubTest)
{
if (_subTests == null)
_subTests = new List<SubTest>();
_subTests.Add(SubTest);
return this;
}
public virtual IReadOnlyList<SubTest> SubTests
{
get
{
if (_subTests == null)
_subTests = new List<SubTest>();
return _subTests.AsReadOnly();
}
}
public void RemoveSubTest( SubTest SubTest )
{
if( _subTests == null )
return;
_subTests.Remove( SubTest );
}
}
使用以下映射,它将值设置为字段而不是只读列表的属性
<bag
name="SubTests" table="SubTest" lazy="true" access="field.camelcase-underscore"
optimistic-lock="false"
>
<key column ="TestID" />
<many-to-many class="SubTest, Domain" column="SubTestID" />
</bag>
您还可以返回
IEnumerable<Abc>
,它是只读迭代器,并提供添加和删除元素的方法。
在我看来,最好的方法是使用 Jon Skeet 建议的
方法返回
IEnumerable<Abc>
:
public IEnumerable<Abc> Abcs {
get { return list.Skip(0); }
}
如果您不担心消费者将
IEnumerable<T>
投射回
IList<T>
,您可以直接返回
IEnumerable<T>
。
ReadOnlyCollection<T>
有一些严重的缺陷,第一个是它实现了
IList<T>
,所以它确实有 Add 和 Remove 方法。如果消费者忽略检查其 ReadOnly 属性,这可能会导致运行时错误。我强烈建议不要使用它。