从 IList<> 返回 ReadOnlyCollection

发布于 2024-12-02 06:43:33 字数 653 浏览 4 评论 0 原文

好的,所以 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) 来限制添加到此列表,同时不允许使用列表.添加(某些项目)。问题是我使用 NHibernate ,它需要 IList 接口,所以我无法在 IList 上强制转换/调用 AsReadOnly() (它不包含此方法)。

您建议采取什么方法来解决这种情况?我只需要一种方法让 NHibernate 以某种方式设置所需的集合,但我还需要限制用户。

OK, so List<> contains the AsReadOnly() which gives you the ReadOnlyCollection. What I need is to have a field of IList type, and a property which would return a ReadOnlyCollection for this list.

Example class:

class Test
{
   private IList<Abc> list;

   public AddToList(Abc someItem) { /* adds inside the list */... }

   public ReadOnlyCollection<Abc> List { get { return ??? } } // <- no "set" here!
}

The scenario is following: I need to have some custom logic inside my class when the item is added into the list, and I want to restrict adding to this list by calling AddToList(someitem), while not allowing the usage of list.Add(someItem). The problem is that I use NHibernate which requires the IList interface, so I cannot cast / call the AsReadOnly() on the IList (it does not contain this method).

What way would you recommend to solve this situation? I simply need a way for NHibernate to set the needed collection in some way, but I also need to restrict users.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

守望孤独 2024-12-09 06:43:33

您可以模拟 AsReadOnly()

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

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

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

You can just emulate AsReadOnly():

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

UPDATE:
This doesn't create a copy of list. ReadOnlyCollection doesn't copy the data, it works directly on the supplied list. See documentation:

A collection that is read-only is simply a collection with a wrapper that prevents modifying the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes.
This constructor is an O(1) operation.

¢蛋碎的人ぎ生 2024-12-09 06:43:33

尝试

return new ReadOnlyCollection<Abc> (list);

try

return new ReadOnlyCollection<Abc> (list);
愁杀 2024-12-09 06:43:33

使用以下方式,

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>

Use following way,

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 );            
        }

    }

use following mapping, and it would sets the value to the field not to the property which is read only list

<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>
落花随流水 2024-12-09 06:43:33

您还可以返回 IEnumerable,它是只读迭代器,并提供添加和删除元素的方法。

You can also return IEnumerable<Abc> which is read only iterator and provide methods for adding and removing elements.

坚持沉默 2024-12-09 06:43:33

在我看来,最好的方法是使用 Jon Skeet 建议的方法

public IEnumerable<Abc> Abcs {
    get { return list.Skip(0); }
}

如果您不担心消费者将 IEnumerable 投射回IList 您可以只返回 IEnumerable

ReadOnlyCollection 有一些严重的缺陷,主要的缺陷是它实现了 IList,因此它确实具有 Add 和 Remove 方法。如果消费者忽略检查其 ReadOnly 属性,这可能会导致运行时错误。我强烈建议不要使用它。

In my opinion the best way to do this is to return IEnumerable<Abc> using the method suggested by Jon Skeet:

public IEnumerable<Abc> Abcs {
    get { return list.Skip(0); }
}

If you're not worried about consumers casting the IEnumerable<T> back to IList<T> you can just return IEnumerable<T>.

ReadOnlyCollection<T> has some serious flaws, the primary one being that it implements IList<T> so it does have Add and Remove methods. This can lead to runtime errors if consumers neglect to check its ReadOnly property. I strongly recommend against using it.

赠我空喜 2024-12-09 06:43:33

从 .NET 7 开始,IList 接口现在提供了一个可供您使用的扩展方法:

IList.AsReadOnly()

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

As of .NET 7, there's now an extension method available on the IList interface that you can use:

IList.AsReadOnly()

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文