【问题标题】:C# Accessors and CollectionsC# 访问器和集合
【发布时间】:2010-12-23 16:25:39
【问题描述】:

在定义类时,我将类成员作为属性公开:

class ClassA
{
    private String _Name;

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

关于访问器,在类中处理集合的最佳做法是什么

所以如果类被扩展为类似的东西:

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

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

我如何暴露下一个项目?

【问题讨论】:

  • 它将与字符串完全相同...尽管如果您在 .net 3.5 上,我建议使用自动属性!

标签: c# collections


【解决方案1】:

公开集合的只读实例。请注意,内容不是只读的,但 reference 是。

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

【讨论】:

【解决方案2】:

我遇到的命名约定推荐

private String _name;

您也可以使用自动属性来生成与您编写的代码相同的代码

public string Name {get; set;}

对于集合,我不喜欢公开实际的集合,而是公开处理它的方法。

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

否则,您可以使用自动属性将其设为只读

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

【讨论】:

  • 这取决于你的对象是一个集合,还是一个集合。例如。 winforms 控件不是其子项的集合,但 DataGridViewRowCollection 肯定是。
【解决方案3】:

我不知道是否有专门的最佳实践,但有几件事需要考虑。基本方法与其他人所说的相同:

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

这里的重点是确保_Parts 永远不是null。这会导致细微且难以发现的错误。

但是,如果您需要在添加和删除元素时发送事件,您只有两种选择:

  • 使用 List 的子类在适当的时候发送事件
  • 根本不公开列表,只公开AddPart()RemovePart()ListParts()(返回当前列表的副本)。

如果您的需求很简单,只需公开该属性(但要保护它不被分配null)。不然你就得花点心思了。

【讨论】:

    【解决方案4】:

    这取决于您对封装数据存储方式的重视程度。如果您正在做一个轻量级的类,并且您只是提供存储,但希望将访问决策完全留给您的类的使用者,您只需将其公开为标准属性或使其成为自动属性。

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

    如果您想确保变量永远不会为空,请继续使用您的私有支持字段并添加检查。

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

    但是,如果您想控制同步或任何其他类似的操作,您将公开对您正在做的事情合乎逻辑的方法。

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

    【讨论】:

    • @Eric,对于您的迭代器块,返回类型应该是 IEnumerable&lt;string&gt; 而不是 List&lt;string&gt;
    • @Anthony 是的,你是对的。我很着急,因为我看到其他人回答得很快!谢谢。
    【解决方案5】:

    难道你不能做同样的事情吗?除了列表?

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

    【讨论】:

    • 可以,但必须是public List&lt;String&gt; Parts
    • 你指的是小写的p吗?
    【解决方案6】:

    我也会公开为财产

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

    【讨论】:

      【解决方案7】:

      您有很多选择,这实际上取决于您希望对类的公共 API 开放什么样的操作。最常见的方法是:

      • 提供只读属性以返回具有相同类型信息的实际集合实例。
      • 提供一个返回IEnumerable接口的只读属性。
      • 提供一个只读属性,该属性返回集合的 ReadOnlyCollection 包装器。

      同样,这实际上取决于您希望如何公开集合,但上面的 3 个选项在大多数情况下都可以正常工作。如果您有更特殊的要求,例如允许从公共 API 添加到集合中,同时又不允许删除,那么事情会变得更加复杂。

      【讨论】:

        【解决方案8】:

        我们通常会做以下事情:

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

        这可确保在创建对象时实例化集合,并使 _parts 集合的基础引用只读。这意味着您可以添加/删除部件,但不能更改属性指向的内容。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-28
          • 2017-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多