好的,所以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)来限制添加到此列表,同时不允许使用列表。新增(someItem)。问题是我使用 NHibernate ,需要IList接口,因此我无法在IList上转换/调用AsReadOnly()(它不包含此方法)。 / p>
您建议以什么方式解决这种情况?我只需要一种方法让NHibernate以某种方式设置所需的集合,但我还需要限制用户。
答案 0 :(得分:26)
您可以模仿AsReadOnly()
:
public ReadOnlyCollection<Abc> List
{
get { return new ReadOnlyCollection<Abc>(list); }
}
<强>更新强>:
这不会创建list
的副本。 ReadOnlyCollection
不会复制数据,它直接在提供的列表中工作。见documentation:
只读集合只是一个带有包装器的集合,可以防止修改集合;因此,如果对基础集合进行了更改,则只读集合会反映这些更改 该构造函数是O(1)操作。
答案 1 :(得分:6)
试
return new ReadOnlyCollection<Abc> (list);
答案 2 :(得分:2)
在我看来,最好的方法是使用method suggested by 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属性,这可能会导致运行时错误。我强烈建议不要使用它。
答案 3 :(得分:1)
使用以下方式,
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>
答案 4 :(得分:1)
您还可以返回IEnumerable<Abc>
这是唯一的迭代器,并提供添加和删除元素的方法。