简体   繁体   English

使用 LINQ 更改列表中对象的属性

[英]Change the property of objects in a List using LINQ

I have list of Beam objects.我有Beam对象列表。 How can I change the IsJoist property of the beams when the Width property is greater than 40 using LINQ?Width属性大于 40 时,如何使用 LINQ 更改梁的IsJoist属性?

class Beam
{
    public double Width { get; set; }
    public bool IsJoist { get; set; }
}

var bm1 = new Beam { Width = 40 };
var bm2 = new Beam { Width = 50 };
var bm3 = new Beam { Width = 30 };
var bm4 = new Beam { Width = 60 };

var Beams = new List<Beam> { bm1, bm2, bm3, bm4 };

Here is what I have done but I'm only getting a List.这是我所做的,但我只得到一个列表。 I want the new list to be the same as the original one except that the IsJoist property for some beams will be set to true.我希望新列表与原始列表相同,只是某些梁的 IsJoist 属性将设置为 true。

var result = Beams
    .Where(x => x.Width > 40)
    .Select(x => x.IsJoist = true)
    .ToList();

I was able to implement this as below.我能够实现如下。 Is it ok since LINQ is meant for queries?可以因为 LINQ 用于查询吗?

var result = Beams
    .Where(x => x.Width > 40)
    .Select(x =>
    {
        x.IsJoist = true;
        return x;
    })
    .ToList();

If your solution must be completely Linq, you could do如果您的解决方案必须完全是 Linq,您可以这样做

Beams.Where(x => x.Width > 40).ToList().ForEach(b => b.IsJoist = true);

However, that is not an ideal way to implement this (@Jacob's answer is a better one).但是,这不是实现此目的的理想方法(@Jacob 的答案更好)。 Check out Eric Lippert's blog entry on the topic.查看 Eric Lippert 关于该主题的博客条目。 The most important lines for me are对我来说最重要的线路是

The first reason is that doing so violates the functional programming principles that all the other sequence operators are based upon.第一个原因是这样做违反了所有其他序列运算符所基于的函数式编程原则。 Clearly the sole purpose of a call to this method is to cause side effects.显然,调用此方法的唯一目的是引起副作用。 The purpose of an expression is to compute a value, not to cause a side effect.表达式的目的是计算一个值,而不是产生副作用。 The purpose of a statement is to cause a side effect.声明的目的是引起副作用。

https://ericlippert.com/2009/05/18/foreach-vs-foreach/ https://ericlippert.com/2009/05/18/foreach-vs-foreach/

Note that ToList() is called because List<T> provides a ForEach() method, while Linq in general does not offer such an extension method for the reasons Eric Lippert cites in that blog entry.请注意,调用ToList()是因为List<T>提供了ForEach()方法,而由于 Eric Lippert 在该博客条目中引用的原因,Linq 通常不提供此类扩展方法。

UPDATE更新

Your code both updates entities in the original list (changes IsJoist to true for certain conditions) and returns references to the objects that were updated.您的代码既更新原始列表中的实体(在某些条件下将 IsJoist 更改为true )并返回对已更新对象的引用。 If that is what you intended, the code functions.如果这是您的意图,代码将起作用。 However, Linq is designed with a functional paradigm in mind.但是,Linq 的设计考虑了功能范式。 Introducing side effects within the context of a Linq expression violates the functional programming principal behind the extension methods.在 Linq 表达式的上下文中引入副作用违反了扩展方法背后的函数式编程原则。

foreach(Beam beam in Beams.Where(x => x.Width > 40))
{
     beam.IsJoist = true;
} 

To be functionally pure, your linq would not alter the data that it is working on.从功能上讲,您的 linq 不会改变它正在处理的数据。 This means that you would have to .Select(x=> new Beam(x) {IsJoist=true}).这意味着您必须 .Select(x=> new Beam(x) {IsJoist=true})。 Then you would replace your original list with the results.然后,您将用结果替换原始列表。

假设我想将特定对象的 Property Selected 值更改为 true 那么我可以这样做

Beams.Where(x => x.Width > 40).FirstorDefault(z=>z.Selected = true)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM