C# 复制IEnuemrable<;T>;-linq Select未按预期运行
我试图复制一个可枚举项以进行比较,因为将一个可枚举项分配给另一个可枚举项只会创建一个引用,所以第二个可枚举项将像第一个一样更改。我最初以为使用linq Select会创建第二个枚举,但惊讶地发现它最终只是传递了引用 逻辑本身用于确定标记列表是否包含特定显示场景的相同事件,代码如下所示C# 复制IEnuemrable<;T>;-linq Select未按预期运行,c#,linq,C#,Linq,我试图复制一个可枚举项以进行比较,因为将一个可枚举项分配给另一个可枚举项只会创建一个引用,所以第二个可枚举项将像第一个一样更改。我最初以为使用linq Select会创建第二个枚举,但惊讶地发现它最终只是传递了引用 逻辑本身用于确定标记列表是否包含特定显示场景的相同事件,代码如下所示 IEnumerable<Event> lastevents = null; foreach (var tag in tags) { IEnumerable<Event> thisev
IEnumerable<Event> lastevents = null;
foreach (var tag in tags)
{
IEnumerable<Event> thisevents = events.Where(e => e.Tags.Contains(tag));
if (lastevents != null)
{
foreach (var item in thisevents)
{
if (!lastevents.Contains(item))
return true;
}
}
lastevents = thisevents.Select(e => e);
}
IEnumerable lastevents=null;
foreach(标签中的var标签)
{
IEnumerable thisevents=events.Where(e=>e.Tags.Contains(tag));
if(lastevents!=null)
{
foreach(thisevents中的变量项)
{
如果(!lastevents.Contains(项))
返回true;
}
}
lastevents=thisevents.Select(e=>e);
}
在这种情况下,复制可枚举项的最佳方法是什么?最简单的方法是调用或。这两者都具体化了查询。像
Where
和Select
这样的LINQ操作符在可能的情况下是懒惰的-它们知道原始集合,并且只按要求处理数据
当然,通过调用
ToList
/ToArray
,您可以删除对Select
的调用,因为这基本上是一个禁止操作的操作。最简单的方法是调用或。这两者都具体化了查询。像Where
和Select
这样的LINQ操作符在可能的情况下是懒惰的-它们知道原始集合,并且只按要求处理数据
当然,通过调用
ToList
/ToArray
,您可以删除对Select
的调用,因为它基本上是禁止操作的。Select不会复制引用,它会创建一个新的IEnumerable,但使用新的IEnumerable也会使用原始IEnumerable。您真正想要的是将其复制到列表中,以便再次枚举
thisevents.ToList()Select不会复制引用,它会创建一个新的IEnumerable,但使用新的IEnumerable也会使用原始IEnumerable。您真正想要的是将其复制到列表中,以便再次枚举
thisevents.ToList()要复制集合,它必须首先作为集合存在 在您展示的代码中,
thisevents
对象不是一个集合,它只是一个能够从其源events
创建集合的表达式。每次使用thisevents
对象时,它都会通过处理events
中的数据来创建一个新结果
使用Select
将创建一个处理源的表达式,而在本例中,源是一个处理事件的表达式,因此最终结果仍然是一个处理事件的表达式。使用Select
只会将表达式包装到另一个表达式中,不会使集合具体化
当您将表达式指定给lastevents
时,它仍然是一个处理事件的表达式,因此如果更改events
,lastevents
的结果也会随着动态创建而更改
您可以使用ToList
或ToArray
将结果具体化为实际收集:
IEnumerable<Event> lastevents = null;
foreach (var tag in tags) {
IEnumerable<Event> thisevents = events.Where(e => e.Tags.Contains(tag)).ToList();
if (lastevents != null) {
foreach (var item in thisevents) {
if (!lastevents.Contains(item)) {
return true;
}
}
}
lastevents = thisevents;
}
IEnumerable lastevents=null;
foreach(标签中的var标签){
IEnumerable thisevents=events.Where(e=>e.Tags.Contains(tag)).ToList();
if(lastevents!=null){
foreach(thisevents中的变量项){
如果(!lastevents.Contains(项)){
返回true;
}
}
}
lastevents=thisevents;
}
请注意,由于thisevents
是不再依赖于events
的实际集合,因此将引用复制到lastevents
中不是问题。您不必创建集合的另一个副本。要复制集合,它必须首先作为集合存在
在您展示的代码中,thisevents
对象不是一个集合,它只是一个能够从其源events
创建集合的表达式。每次使用thisevents
对象时,它都会通过处理events
中的数据来创建一个新结果
使用Select
将创建一个处理源的表达式,而在本例中,源是一个处理事件的表达式,因此最终结果仍然是一个处理事件的表达式。使用Select
只会将表达式包装到另一个表达式中,不会使集合具体化
当您将表达式指定给lastevents
时,它仍然是一个处理事件的表达式,因此如果更改events
,lastevents
的结果也会随着动态创建而更改
您可以使用ToList
或ToArray
将结果具体化为实际收集:
IEnumerable<Event> lastevents = null;
foreach (var tag in tags) {
IEnumerable<Event> thisevents = events.Where(e => e.Tags.Contains(tag)).ToList();
if (lastevents != null) {
foreach (var item in thisevents) {
if (!lastevents.Contains(item)) {
return true;
}
}
}
lastevents = thisevents;
}
IEnumerable lastevents=null;
foreach(标签中的var标签){
IEnumerable thisevents=events.Where(e=>e.Tags.Contains(tag)).ToList();
if(lastevents!=null){
foreach(thisevents中的变量项){
如果(!lastevents.Contains(项)){
返回true;
}
}
}
lastevents=thisevents;
}
请注意,由于thisevents
是不再依赖于events
的实际集合,因此将引用复制到lastevents
中不是问题。您不必创建集合的另一个副本。是否要更改列表或事件
对象?是否要复制引用或克隆对象?是否要更改列表或事件
对象?要复制引用还是克隆对象?