简体   繁体   English

如何保护 List 的 Add 方法,同时使用 get 属性公开 List?

[英]How to make List's Add method protected, while exposing List with get property?

I have a class named WhatClass that has List field in it.我有一个名为 WhatClass 的类,其中包含 List 字段。 I need to be able to read-only this field, so I used a get property to expose it to other objects.我需要能够只读这个字段,所以我使用了一个 get 属性将它公开给其他对象。

public class WhatClass
{
    List<SomeOtherClass> _SomeOtherClassItems;

    public List<SomeOtherClass> SomeOtherClassItems { get { return _SomeOtherClassItems; } }
}

However it turns out that any object can call然而事实证明,任何对象都可以调用

WhatClass.SomeOtherClassItems.Add(item);

How can I prevent this?我怎样才能防止这种情况?

As others have said, you are looking for the .AsReadOnly() extension method.正如其他人所说,您正在寻找.AsReadOnly()扩展方法。

However, you should store a reference to the collection instead of creating it during each property access:但是,您应该存储对集合的引用,而不是在每个属性访问期间创建它:

private readonly List<SomeOtherClass> _items;

public WhatClass()
{
    _items = new List<SomeOtherClass>();

    this.Items = _items.AsReadOnly();
}

public ReadOnlyCollection<SomeOtherClass> Items { get; private set; }

This is to ensure that x.Items == x.Items holds true, which could otherwise be very unexpected for API consumers.这是为了确保x.Items == x.Items成立,否则 API 使用者可能会非常意外。

Exposing ReadOnlyCollection<> communicates your intent of a read-only collection to consumers.公开ReadOnlyCollection<>将您对只读集合的​​意图传达给消费者。 Changes to _items will be reflected in Items ._items更改将反映在Items

You're looking for the ReadOnlyCollection<T> class , which is a read-only wrapper around an IList<T> .您正在寻找ReadOnlyCollection<T>,它是IList<T>的只读包装器。

Since the ReadOnlyCollection<T> will reflect changes in the underlying list, you don't need to create a new instance every time.由于ReadOnlyCollection<T>将反映基础列表中的更改,因此您无需每次都创建一个新实例。

For example:例如:

public class WhatClass {
    public WhatClass() {
        _SomeOtherClassItems = new List<SomeOtherClass>();
        SomeOtherClassItems = _SomeOtherClassItems.AsReadOnly();
    }

    List<SomeOtherClass> _SomeOtherClassItems;

    public ReadOnlyCollection<SomeOtherClass> SomeOtherClassItems { get; private set; }
}

Use List<T>.AsReadOnly :使用List<T>.AsReadOnly

public ReadOnlyCollection<SomeOtherClass> SomeOtherClassItems
{
    get
    {
        return _SomeOtherClassItems.AsReadOnly();
    }
}

This will return a ReadOnlyCollection , which will throw an exception if a client calls Add through the interface.这将返回一个ReadOnlyCollection ,如果客户端通过接口调用 Add ,它将抛出异常。 In addition, the ReadOnlyCollection type does not expose a public Add method.此外,ReadOnlyCollection 类型不公开公共 Add 方法。

How about using AsReadOnly() ?使用AsReadOnly()怎么样? - MSDN Documentation - MSDN 文档

You can just use ToList() to return a copy of the list instead.您可以只使用 ToList() 来返回列表的副本。 Other classes can do what they like to the copy it won't alter your original list.其他类可以对副本做他们喜欢做的事情,它不会改变您的原始列表。

You should make it clear in the name that they are getting a copy.您应该在名称中明确表示他们正在获取副本。

using System.Linq;

public class WhatClass
{
    List<SomeOtherClass> _SomeOtherClassItems;

    public List<SomeOtherClass> SomeOtherClassItems { get { return _SomeOtherClassItems.ToList(); } }
}

Although others have pointed out the use of ReadOnlyCollection , it's worth noting that there also exists a cool ReadOnlyObservableCollection .虽然其他人已经指出了ReadOnlyCollection的使用,但值得注意的是,还有一个很酷的ReadOnlyObservableCollection It can be really useful in bindings and view models.它在绑定和视图模型中非常有用。 As pointed here :正如这里指出的

This class is a read-only wrapper around an ObservableCollection.此类是 ObservableCollection 的只读包装器。 If changes are made to the underlying collection, the ReadOnlyObservableCollection reflects those changes.如果对基础集合进行了更改,则 ReadOnlyObservableCollection 会反映这些更改。 To be notified of the changes to this class, subscribe to the CollectionChanged or PropertyChanged event.要收到此类更改的通知,请订阅 CollectionChanged 或 PropertyChanged 事件。

You can simply expose this ReadOnlyObservableCollection and make changes to the underlying collection and rest assured that your view is getting updated.您可以简单地公开这个ReadOnlyObservableCollection并对基础集合进行更改,并确保您的视图正在更新。

List<T> implements IReadOnlyList<T> since .NET Framework 4.5 , so an internal list can be exposed as IReadOnlyList<T> instead for that purpose. List<T> 从 .NET Framework 4.5 开始实现IReadOnlyList<T> ,因此内部列表可以公开为IReadOnlyList<T>来代替。

public class WhatClass
{
    List<SomeOtherClass> _SomeOtherClassItems;

    public IReadOnlyList<SomeOtherClass> SomeOtherClassItems => _SomeOtherClassItems;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM