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;
}
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
, 2
和3
。
从方法名称中不清楚返回副本,因此您可能希望将其更改为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)公开原始列表mList
。Add()
或AddRange()
或Clear()
影响(修改)它。
(2)如果mList
为空,返回null
!