为什么IEnumerable投影不是不可变的?

本文关键字:不可变 IEnumerable 投影 为什么 | 更新日期: 2023-09-27 17:52:34

假设我的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)

从延迟执行的角度来看,这一切都很好,这个问题之前已经讨论过了,比如这里和这里。然而,我的问题是为什么枚举器实现不返回不可变对象;如果不能保证多个枚举的持久性,那么设置值的功能又有什么用呢?

也许这不是一个很好的问题,但我相信你的答案会很有启发性。

为什么IEnumerable投影不是不可变的?

我的问题是为什么枚举器实现不返回不可变对象

你希望他们怎么做?它们是所使用的任何类型的序列-您会期望发生什么:

var builders = new string[] { "foo", "bar" }.Select(x => new StringBuilder(x));

?您会期望它(无论在这种情况下"它"是什么)自动创建一个与StringBuilder相同的API的新类型,但神奇地使其不可变吗?它如何检测突变?

基本上,你所要求的是不可行的——你可以有一个元素类型是可变的序列,所以在迭代它的时候,你可以改变生成的引用所引用的对象。

枚举数并不意味着提供不变性。它们是循环遍历集合的一种方式,就像循环遍历带索引的标准数组一样。由于您可以访问底层对象,这意味着您可以更改它们。是的,c#中的不可变性在集合方面是一个新事物,这在枚举器中是意想不到的,也不可能实现的。

相关文章: