naw*_*fal 4 c# linq immutability
这是如何Cast<T>在框架中实现的:
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
IEnumerable<TResult> enumerable = source as IEnumerable<TResult>;
if (enumerable != null)
{
return enumerable; //the culprit
}
return Enumerable.CastIterator<TResult>(source);
}
Run Code Online (Sandbox Code Playgroud)
我看到的问题是,Cast<T>如果满足某些标准,则返回实际的可枚举数.例如,这不应该发生:
var x = new List<string> { "1" };
var y = x.Cast<string>();
x.Add("2"); //reflects in y "immediately", since they are the same reference.
Run Code Online (Sandbox Code Playgroud)
或者可能是一个更实际的例子:
object[] x = new[] { "1" };
var y = x.Cast<string>();
x[0] = "2"; //reflects in y "immediately", since they are the same reference.
Run Code Online (Sandbox Code Playgroud)
文档页面甚至说:这个方法是通过使用延迟执行来实现的.,但不是真的在每种情况下(如上所示).同样,我可以认为AsEnumerable是另一个自我回归的罪魁祸首.
它可以旅行的情况:
var x = new List<string> { "1" }; //data source
var y = x.Cast<string>(); //query
((List<string>)y).Add("2"); //did something with the query
// Whoa, got the data source itself changed by tinkering the query
Run Code Online (Sandbox Code Playgroud)
问题:
不要将两种方法AsEnumerable和Cast违反LINQ的扩展方法的功能性质是什么?可能是我错误地阅读了一些指南?
在System.Linq命名空间中是否有更多类似的扩展方法返回自身?
好的,我认为每个linq方法都会在枚举时生成一个新的序列,这不是这里的情况.也许我不需要这样想.
但似乎存在关于延期执行的混淆.我预计IEnumerable<T>只有在执行(我的意思是枚举)查询时,才会在linq查询中反映数据源的更改.例如,请考虑以下示例:
var x = new List<int> { 1 };
var y = x.Cast<SomeEnum>();
x.Add(2); //at this stage the change to x is not reflected in y yet
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,如果我添加一个新元素x,y仍然指向一个查询,并且x没有反映更改y.我认为这是延迟执行,从某种意义上说,必须枚举它以查看更改.在前面的例子中,变化立即反映在y.所以我认为这不是真正的延期执行.按照这里的答案,我的想法是错误的.
小智 5
您给出的操作源数组的示例会影响枚举的输出,实际上是由于延迟执行.所以他们不建议延期执行不会发生.
如果您获得对原始列表的引用,或者对引用没有区别CastIterator.后者将懒惰地评估来源,因此两种情况都会反映出变化.
如果C#是纯函数式语言,Linq可能是延迟的(延迟的)并且会返回一个不会随时间变化的迭代.
但是C#不是一种纯粹的功能语言.
Linq团队必须选择并实施懒惰部分.在Linq中强制执行的不变性会更加昂贵.但是如果你想要不变性,你可以得到它:只需停止更改源,或ToArray()在适当的时候使用快照.