简体   繁体   English

C#访问者和集合

[英]C# Accessors and Collections

When defining classes I expose class members as properties along the lines of : 在定义类时,我将类成员公开为以下行的属性:

class ClassA
{
    private String _Name;

    public String Name
    {
        get { return _Name; }
        set { _Name = value; }
    }
 }

What is best practice for dealing with collections within classes, with respect to accessors 对于访问者而言,在类中处理集合的最佳实践是什么

So if the class is extended to something like : 因此,如果将类扩展为类似于:

class ClassA
{
    private String _Name;
    private List<String> _Parts = new List<String>();

    public String Name
    {
        get { return _Name; }
        set { _Name = value; }
    }
 }

How do I expose the next item? 如何公开下一个项目?

Expose a read-only instance of the collection. 公开集合的只读实例。 Note that the contents are not read-only, but the reference is. 请注意,内容不是只读的,但参考是。

public IList<String> Parts { get; private set; }

The naming conventions I've come across recommend 我遇到的命名约定建议

private String _name;

Also you could use automatic properties which generate the same code you've written 您还可以使用自动属性生成与您编写的代码相同的代码

public string Name {get; set;}

For collections, I don't like to expose the actual collection but methods to work on it. 对于集合,我不喜欢公开实际的集合,而是公开它的方法。

public void Add(...
public void Remove(...

Otherwise you could make it readonly with an automatic property 否则,您可以使用自动属性将其设为只读

public IList<string> Parts {get; private set;}

It depends on how serious you are about encapsulating the way the data is stored. 这取决于你对封装数据存储方式的严肃程度。 If you're doing a lightweight class and you are just providing the storage but want to leave the accessing decisions completely up to the consumer of your class, you just expose it like a standard property or make it an auto-property. 如果您正在进行轻量级课程并且您只是提供存储但是想要完全取决于您的类的使用者的访问决策,那么您只需将其公开为标准属性或使其成为自动属性。

public List<String> Parts { get; private set; }

If you want to ensure the variable is never null, continue to use your private backing field and add checks. 如果要确保变量永远不为null,请继续使用私有支持字段并添加检查。

private List<String> _Parts;
public IList<String> Parts
{
    get
    {
        if (_Parts == null)
            _Parts = new List<String>();
        return _Parts;
    }
    private set
    {
        if (value != null)
            _Parts = value;
    }
}

If, however, you want to control synchronization, or anything else of that sort, you'd expose methods that are logical for what you're doing. 但是,如果您想要控制同步或其他任何类型的同步,那么您将公开对您正在进行的操作具有逻辑性的方法。

public void AddPart(String part);
public void RemovePart(String part);
public String GetPart(int index);
public IEnumerable<String> GetAllParts()
{
    foreach(String part in _Parts)
        yield return part;
}

I don't know if there is specifically a best practice in place, but there are a couple things to consider. 我不知道是否有具体的最佳实践 ,但有几件事需要考虑。 The basic approach is the same as what others have stated: 基本方法与其他人所说的相同:

public List<String> Parts
{
    get { return _Parts; }
    private set { _Parts = value; }
}

The important point here is to make sure that _Parts is never null . 这里重点是确保_Parts永远不为null That leads to subtle and hard to discover bugs. 这导致了微妙而难以发现的错误。

However, if you need to send events when elements are added and removed you have only two options: 但是,如果您需要在添加和删除元素时发送事件,则只有两个选项:

  • Use a subclass of List that sends the events when appropriate 使用List的子类,在适当的时候发送事件
  • Don't expose the List at all, and merely expose the AddPart() , RemovePart() , and ListParts() (that returns a copy of the current list). 根本不公开List,只显示AddPart()RemovePart()RemovePart() ListParts() (返回当前列表的副本)。

If your needs are simple, just expose the property (but protect it from being assigned null ). 如果您的需求很简单,只需公开属性(但保护它不被指定为null )。 Otherwise you'll have to be a bit more fancy. 否则你将不得不更加花哨。

Couldn't you just do the same - but for the list? 难道你不能这样做 - 但是对于名单?

public List<String> parts
    {
        get { return _Parts; }
        set { _Parts = value; }
    }

我也将作为财产公开

public List<string> Parts { get; set; }

You have a bunch of options and it really depends on what kind of operations you want to open up to the public API of your class. 您有很多选项,这实际上取决于您希望打开类的公共API的操作类型。 The most common approaches are: 最常见的方法是:

  • Provide a readonly property to returns the actual collection instance with the same type information. 提供readonly属性以返回具有相同类型信息的实际集合实例。
  • Provide a readonly property that returns an IEnumerable interface. 提供一个返回IEnumerable接口的readonly属性。
  • Provide a readonly property that returns a ReadOnlyCollection wrapper of the collection. 提供readonly属性,该属性返回集合的ReadOnlyCollection包装。

Again, it really depends on how you want to expose the collection, but the 3 options above will work fine in most scenarios. 同样,它实际上取决于您希望如何公开集合,但上述3个选项在大多数情况下都能正常工作。 If you have more specialized requirements like allowing additions to the collection from the public API while at the same time disallowing removals then things get a bit more complicated. 如果您有更多专门的要求,例如允许从公共API添加到集合中,同时禁止删除,那么事情会变得复杂一些。

We typically do the following: 我们通常会执行以下操作:

private Collection<String> _parts = new Collection<String>();
public Collection<String> Parts {
  get { return _parts; }
}

This ensures that the collection is instantiated when the object is created and it makes the underlying reference for the _parts collection read only. 这可确保在创建对象时实例化集合,并使_parts集合的基础引用只读。 Which means you can add/remove parts but you can't change what the property points to. 这意味着您可以添加/删除部件,但无法更改属性指向的部分。

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

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