【问题标题】:AddRange in give public access to listAddRange in 授予对列表的公共访问权限
【发布时间】:2016-01-17 14:49:20
【问题描述】:

我有一些带有以下部分的遗留 C# 代码:

private List<MyClass> mList = new List<MyClass>();

public List<MyClass> getList()
{
   List<MyClass> list = new List<MyClass>();
   list.AddRange(mList);
   return list;
}

不确定AddRange 的用途是什么?我可以改写成:

public List<MyClass> getList()
{
   return mList;
}

【问题讨论】:

  • 是的。从显示的代码来看,应该足够了。
  • 不完全相同,因为getList 创建了一个包含相同对象的新列表,而return mList 甚至返回相同的列表。因此,如果您致电getList().Clear(),原始列表也会被清除。
  • 这个属性有一个丑陋的副作用,因为它暗示你可以通过修改返回的列表来改变所属类的状态。返回IEnumerable 或将其作为方法将是合适的做法。

标签: c# .net generics properties


【解决方案1】:

没有。

如果您只使用return mlist,则返回mlist 实例,而原始代码返回它的浅表副本。


假设你的班级是这样的:

class Foo
{
    public Foo()
    {
        mList.Add(1);
    }

    private List<int> mList = new List<int>();

    public List<int> getList()
    {
        List<int> list = new List<int>();
        list.AddRange(mList);
        return list;
    }
}

现在你运行

var x = new Foo();
x.getList().Add(2);
x.getList().Add(3);

mList 的内容仍将是单个 1,因为对 getList 的调用返回了 mList 的副本,而不是列表本身。

如果您像在问题中那样更改代码,您将更改 mList,它现在将包含元素 123


从方法名称中并不清楚返回的副本,因此您可能希望将其更改为 GetListCopy(在这种情况下,该方法可以简单地返回 new List&lt;MyClass&gt;(mList)mList.ToList()),或者返回以IReadOnlyList 的形式列出,以明确该列表不应更改。

public IReadOnlyCollection<MyClass> getList()
{
    return mList.AsReadOnly();
}

【讨论】:

  • 这缺乏解释
  • @TimSchmelter 你认为什么没有解释?原始代码返回列表的副本,新代码返回mList 实例。
  • OP好像对C#不是很熟悉,问了一个基本的问题。因此,回答它返回一个浅副本而不是原始列表可能是正确的,但如果 OP 不知道它的含义,它就不是很有帮助。什么时候重要/有所作为? (例如,如果您致电 Clear()
  • @sloth:这有什么不同?因为如果我更改复制列表中的任何值,它将在原始列表中得到很好的更改。请说清楚。使用复制实例而不是原始实例有什么好处?
【解决方案2】:

不,你不能。 这可能会导致您的软件出现一些意外行为,因为代码会创建一个新的 List 实例,并且每次调用该方法时,您的解决方案都会返回相同的实例。

【讨论】:

    【解决方案3】:

    如前所述,如果您只使用 return mList;,它将返回原始列表,而不是它的副本。

    不过你可以使用 :

    来简化它
    public List<MyClass> getList
    {
       return mList.ToList();  // returns copy of original list
    }
    

    【讨论】:

      【解决方案4】:

      这里的唯一目的是克隆原始列表以使其保持不变。 但是,最好重新编写这个属性并将其转为方法:

      public List<MyClass> getList()
      {
         // note, that Enumerable.ToList() does the same
         return new List(mList);
      }
      

      List&lt;T&gt; 构造函数检查源IEnumerable&lt;T&gt; 中的ICollection&lt;T&gt; 实现,并正确设置初始容量。由于每次调用都会创建一个新实例,所以这不应该是一个属性,而是一个方法。

      【讨论】:

        【解决方案5】:

        Tim 和 Sloth 的评论已经给出了正确的解释。

        只是补充一点:

        private List<MyClass> mList = new List<MyClass>();
        
        public List<MyClass> getList1()
        {
            List<MyClass> list = new List<MyClass>();
            list.AddRange(mList);
            return list;
        }
        
        public List<MyClass> getList2()
        {
            return mList;
        }
        

        getlis1() -
        (1) 保持原始列表安全Add()AddRange()Clear() 不影响它。
        (2) 如果mList 为空,抛出异常!

        getlis2() -
        (1) 暴露原始列表mListAdd()AddRange()Clear() 影响(修改)它。
        (2) 如果mList 为空,则返回null

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多