AddRange允许公众访问列表

本文关键字:列表 访问 许公众 AddRange | 更新日期: 2023-09-27 18:18:14

我有一些遗留的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;
}

AddRange允许公众访问列表

No.

如果您只使用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,它现在将包含元素1, 23


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

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

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

但是你可以通过使用:

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

不行。这可能会导致一些意想不到的行为在你的软件中,因为代码,因为它是创建List的一个新的实例,你的解决方案有相同的实例返回每次调用该方法。

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

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

List<T>构造函数检查源IEnumerable<T>ICollection<T>的实现,并正确设置初始容量。因为每次调用都会创建一个新的实例,所以它不应该是一个属性,而应该是一个方法。

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 !