kdb*_*man 3 c# arrays collections
我刚刚阅读了Eric Lippert的" Arrays被认为是有害的 "文章.他告诉他的读者,他们"可能不应该将数组作为公共方法或财产的价值返回",其理由如下(稍微解释):
现在调用者可以使用该数组并用他们喜欢的任何内容替换它的内容.回归的明智之举是
IList<>
.你可以自己构建一个很好的只读集合对象,然后根据需要传递对它的引用.
在本质上,
数组是变量的集合.调用者不需要变量,但是如果这是获取值的唯一方法,它将采用它们.但是被调用者和调用者都不希望这些变量发生变化.
为了理解变量与值的含义,我构建了具有Array
和IList<>
字段的demo类,以及返回对两者的引用的方法. 这是在C#Pad上.
class A {
private readonly int[] arr = new []
{
10, 20, 30, 40, 50
};
private readonly List<int> list = new List<int>(new []
{
10, 20, 30, 40, 50
});
public int[] GetArr()
{
return arr;
}
public IList<int> GetList()
{
return list;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,这种GetArr()
方法是Lippert的不良做法,GetList()
是他明智的做法.这是一个不良调用者可变性行为的演示GetArr()
:
var a = new A();
var arr1 = a.GetArr();
var arr2 = a.GetArr();
Console.WriteLine("arr1[2]: " + arr1[2].ToString()); // > arr1[2]: 30
Console.WriteLine("arr2[2]: " + arr2[2].ToString()); // > arr2[2]: 30
// ONE CALLER MUTATES
arr1[2] = 99;
// BOTH CALLERS AFFECTED
Console.WriteLine("arr1[2]: " + arr1[2].ToString()); // > arr1[2]: 99
Console.WriteLine("arr2[2]: " + arr2[2].ToString()); // > arr2[2]: 99
Run Code Online (Sandbox Code Playgroud)
但我不明白他的区别- 的IList<>
参考值具有相同的来电者的突变的问题:
var a = new A();
var list1 = a.GetList();
var list2 = a.GetList();
Console.WriteLine("list1[2]: " + list1[2].ToString()); // > list1[2]: 30
Console.WriteLine("list2[2]: " + list2[2].ToString()); // > list2[2]: 30
// ONE CALLER MUTATES
list1[2] = 99;
// BOTH CALLERS AFFECTED
Console.WriteLine("list1[2]: " + list1[2].ToString()); // > list1[2]: 99
Console.WriteLine("list2[2]: " + list2[2].ToString()); // > list2[2]: 99
Run Code Online (Sandbox Code Playgroud)
显然,我相信Eric Lippert知道他在说什么,所以我在哪里误解了他?返回的IList<>
引用以什么方式比引用更安全Array
?
如果这篇文章今天已经写好了几乎肯定会建议使用IReadOnlyList<T>
,但是在撰写该文章的2008年并不存在这种类型.具有只读可索引列表接口的唯一受支持的方法是使用IList<T>
并且根本不实现变异操作.这确实让你返回一个调用者不能改变的对象,尽管它不一定清楚(特别是来自API)该对象实际上是不可变的.从那时起,.NET中的这个缺点就得到了补救.
归档时间: |
|
查看次数: |
603 次 |
最近记录: |