How to modify only one or two field(s) in LINQ projections?

岁酱吖の 提交于 2021-02-19 01:17:32

问题


I have this LINQ query:

List<Customers> customers = customerManager.GetCustomers();

return customers.Select(i => new Customer {
    FullName = i.FullName,
    Birthday = i.Birthday, 
    Score = i.Score,
    // Here, I've got more fields to fill
    IsVip = DetermineVip(i.Score)
}).ToList();

In other words, I only want one or two fields of the list of the customers to be modified based on a condition, in my business method. I've got two ways to do this,

  1. Using for...each loop, to loop over customers and modify that field (imperative approach)
  2. Using LINQ projection (declarative approach)

Is there any technique to be used in LINQ query, to only modify one property in projection? For example, something like:

return customers.Select(i => new Customer {
    result = i // telling LINQ to fill other properties as it is
    IsVip = DetermineVip(i.Score) // then modifying this one property
}).ToList();

回答1:


you can use

return customers.Select(i => {
    i.IsVip = DetermineVip(i.Score);
    return i;
}).ToList();



回答2:


Contrary to other answers, you can modify the source content within linq by calling a method in the Select statement (note that this is not supported by EF although that shouldn't be a problem for you).

return customers.Select(customer => 
{
    customer.FullName = "foo";
    return customer;
});



回答3:


No, Linq was designed to iterate over collections without affecting the contents of the source enumerable.

You can however create your own method for iterating and mutating the collection:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}

You can then use as follows:

return customers.ToList()
                .ForEach(i => i.IsVip = DetermineVip(i.Score))
                .ToList();

Note that the first ForEach will clone the source list.




回答4:


You "can", if you create a copy constructor, which initializes a new object with the values of an existing object:

partial class Customer
{
    public Customer(Customer original)
    {
        this.FullName = original.FullName;
        //...
    }
}

Then you can do:

return customers.Select(i => new Customer(i) { IsVip = DetermineVip(i.Score)})
    .ToList()

But the downfall here is you will be creating a new Customer object based on each existing object, and not modifying the existing object - this is why I have put "can" in quotes. I do not know if this is truly what you desire.




回答5:


As customers already is a List, you can use the ForEach method:

customers.ForEach(c => c.IsVip = DetermineVip(c.Score));


来源:https://stackoverflow.com/questions/15378257/how-to-modify-only-one-or-two-fields-in-linq-projections

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!