【问题标题】:Update class property inside Enumerable.Zip linq c#更新 Enumerable.Zip linq c# 中的类属性
【发布时间】:2016-03-04 11:31:58
【问题描述】:

我想从外部列表更新 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

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

OUTPUT:
3
3
3

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

【问题讨论】:

    标签: c# linq ienumerable


    【解决方案1】:

    Enumerable.Repeat(a, b) 生成一个包含b 乘以a 的序列。所以你会得到一个包含三倍于 same 实例的序列(你只实例化 one new MyClass())。

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

    创建myclasses 的更好方法是

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

    注意,创建带有副作用的序列是 often a bad idea。您实际上并没有使用Zip 返回的序列,而是仅将这个 查询 用于它在 lambda 中的副作用。

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

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

    更新

    您现在只得到0s 作为输出的原因是延迟执行(再次说明:使用像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

    【讨论】:

    • 是的,myclasses 的创建与问题是分开的,我只对Zip 的更新感兴趣。正如您所写,我使用Enumerable.Range 更正了myclassess 的创建,但这仍然不起作用。在这种情况下,Zip 什么都不做(它会打印全零)。同样,我不明白为什么不调用属性设置器。
    • 我无法相信我只用了几行就犯了几个错误:)。 Tnx 很好的解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2011-07-04
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    相关资源
    最近更新 更多