从IList<>返回ReadOnlyCollection

问题描述 投票:0回答:6

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

c# .net nhibernate ilist readonly-collection
6个回答
33
投票

你可以模仿

AsReadOnly()

public ReadOnlyCollection<Abc> List
{
    get { return new ReadOnlyCollection<Abc>(list); }
}

更新
这不会创建

list
的副本。
ReadOnlyCollection
不复制数据,它直接在提供的列表上工作。请参阅文档

只读集合只是带有防止修改集合的包装器的集合;因此,如果对基础集合进行更改,只读集合会反映这些更改。
这个构造函数是一个 O(1) 操作。


7
投票

尝试

return new ReadOnlyCollection<Abc> (list);

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>

1
投票

您还可以返回

IEnumerable<Abc>
,它是只读迭代器,并提供添加和删除元素的方法。


1
投票

在我看来,最好的方法是使用 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 属性,这可能会导致运行时错误。我强烈建议不要使用它。


0
投票
从 .NET 7 开始,

IList

 接口上现在提供了一个扩展方法,您可以使用:

IList.AsReadOnly()


https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.collectionextensions.asreadonly?view=net-8.0

© www.soinside.com 2019 - 2024. All rights reserved.