更新 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.Repeat(a, b)
生成一个包含b
次a
的序列。因此,您会得到一个包含三次相同实例的序列(您只实例化一个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
。