更新 Enumerable.Zip linq c# 中的类属性

本文关键字:属性 Enumerable Zip linq 更新 | 更新日期: 2023-09-27 18:37:17

我想从外部列表中更新IEnumerable中的每个类属性。

class MyClass
{
    public int Value { get; set; }            
}

我尝试了以下方法

var numbers = new List<int>() { 1, 2, 3 };
var myclasses = Enumerable.Repeat(new MyClass(), numbers.Count);  
myclasses.Zip(numbers, (a, b) => a.Value = b).ToList();           // Set each property [Not working as expected]
myclasses.ToList().ForEach(x => Console.WriteLine(x.Value));      // Print all properties

我希望以前的代码将分别在 1,2,3 的myclasses中设置Value属性。但是此代码集3在每个属性中并打印:

OUTPUT:
3
3
3

我不明白这种行为。有人可以解释为什么会发生这种情况以及使用 LINQ 执行此操作的正确方法是什么。

更新 Enumerable.Zip linq c# 中的类属性

>Enumerable.Repeat(a, b)生成一个包含ba的序列。因此,您会得到一个包含三次相同实例的序列(您只实例化一个new MyClass())。

因此,在上次执行 a.Value = b 时,您将单个 MyClass 实例的 Value 属性设置为 3 ,并且WriteLine中的x始终是相同的实例,包含 Value = 3

创建myclasses的更好方法是

var myclasses = Enumerable.Range(1, numbers.Count).Select(i => new MyClass());

请注意,创建具有副作用的序列通常是一个坏主意。您实际上不使用 Zip 返回的序列,而是仅将此查询用于 lambda 中的副作用。

我想在您的实际应用程序中,myclasses的创建和通过Zip更新比您的问题更加分离。但如果没有,你可以把它全部简化为:

var myclasses = numbers.Select(i => new MyClass { Value = i });

更新

您现在只获得 0 s 作为输出的原因是延迟执行(再次:仅使用像 linq 这样的函数式编程方法来解决其副作用是很棘手的)。

直接的解决方案是在创建中添加ToList

var myclasses = Enumerable.Range(1, numbers.Count).Select(i => new MyClass()).ToList();

否则,类仅在以下行实例化:

myclasses.Zip(numbers, (a, b) => a.Value = b).ToList(); 

并且创建的类作为序列返回,然后由ToList()转换为List。但是您不使用该返回值。

所以在下一行

myclasses.ToList().ForEach(x => Console.WriteLine(x.Value));

创建类的新实例

myclasses,正如您定义的那样,它只是一个查询,而不是该查询的答案

所以我的最终建议:

var myclasses = Enumerable.Range(1, numbers.Count).Select(i => new MyClass());
var updatedClasses = myclasses.Zip(numbers, (a, b) => {a.Value = b; return a;}).ToList(); 
updatedClasses.ForEach(x => Console.WriteLine(x.Value));

请注意,我在 Zip 中更改了 lambda 以返回类的实例而不是 int