从IList<>返回ReadOnlyCollection

时间:2011-08-29 08:06:19

标签: c# .net nhibernate ilist readonly-collection

好的,所以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以某种方式设置所需的集合,但我还需要限制用户。

5 个答案:

答案 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>这是唯一的迭代器,并提供添加和删除元素的方法。