假设我的Awesome
类有一个属性Bazinga
,这是一个默认值为" default value"的String
,我可以去:
var enumerableOfAwesome = Enumerable
.Range(1, 5)
.Select(n => new Awesome());
foreach (var a in enumerableOfAwesome)
a.Bazinga = "New value";
您可能已经意识到,如果您希望找到安全地隐藏在所有Bazinga
中的"新值"字符串,再次枚举enumerableOfAwesome
将不会使您高兴。相反,将它们输出到控制台将呈现:
默认值
默认值
默认值
默认值
默认值
(。. NET Fiddle here)
从延迟执行的角度来看,这一切都很好,这个问题之前已经讨论过了,比如这里和这里。然而,我的问题是为什么枚举器实现不返回不可变对象;如果不能保证多个枚举的持久性,那么设置值的功能又有什么用呢?
也许这不是一个很好的问题,但我相信你的答案会很有启发性。
我的问题是为什么枚举器实现不返回不可变对象
你希望他们怎么做?它们是所使用的任何类型的序列-您会期望发生什么:
var builders = new string[] { "foo", "bar" }.Select(x => new StringBuilder(x));
?您会期望它(无论在这种情况下"它"是什么)自动创建一个与StringBuilder
相同的API的新类型,但神奇地使其不可变吗?它如何检测突变?
基本上,你所要求的是不可行的——你可以有一个元素类型是可变的序列,所以在迭代它的时候,你可以改变生成的引用所引用的对象。
枚举数并不意味着提供不变性。它们是循环遍历集合的一种方式,就像循环遍历带索引的标准数组一样。由于您可以访问底层对象,这意味着您可以更改它们。是的,c#中的不可变性在集合方面是一个新事物,这在枚举器中是意想不到的,也不可能实现的。