我想改变一个LINQ查询结果对象的一些属性,而不需要创建一个新的对象和手动设置每个属性。这可能吗?
例子:
var list = from something in someList
select x // but change one property
我想改变一个LINQ查询结果对象的一些属性,而不需要创建一个新的对象和手动设置每个属性。这可能吗?
例子:
var list = from something in someList
select x // but change one property
当前回答
这对于标准查询操作符是不可能的——它是语言集成查询,而不是语言集成更新。但是您可以将更新隐藏在扩展方法中。
public static class UpdateExtension
{
public static IEnumerable<Car> ChangeColorTo(
this IEnumerable<Car> cars, Color color)
{
foreach (Car car in cars)
{
car.Color = color;
yield return car;
}
}
}
现在您可以像下面这样使用它。
cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
其他回答
var item = (from something in someList
select x).firstordefault();
会得到item,然后item。prop1=5;更改特定的属性。
或者您想从db中获得一个项目列表,并让它将返回列表中每个项目的属性prop1更改为指定的值? 如果是这样的话,你可以这样做(我在VB中这样做,因为我更了解它):
dim list = from something in someList select x
for each item in list
item.prop1=5
next
(列表将包含您的更改返回的所有项)
不应该有任何LINQ魔法阻止你这样做。不要使用投影,那会返回一个匿名类型。
User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"
这将修改真实对象,以及:
foreach (User u in UserCollection.Where(u => u.Id > 10)
{
u.Property = SomeValue;
}
在不创建新对象的情况下,我们经常会遇到这种情况,即在列表中包含索引值和第一个和最后一个指标。这允许您知道项在列表、枚举等中的位置,而不必修改现有的类,然后知道您是在列表中的第一个项还是最后一个项。
foreach (Item item in this.Items
.Select((x, i) => {
x.ListIndex = i;
x.IsFirst = i == 0;
x.IsLast = i == this.Items.Count-1;
return x;
}))
你可以简单地扩展任何类,使用:
public abstract class IteratorExtender {
public int ListIndex { get; set; }
public bool IsFirst { get; set; }
public bool IsLast { get; set; }
}
public class Item : IteratorExtender {}
由于我在这里没有找到我认为最好的解决方案的答案,下面是我的方法:
使用“选择”来修改数据是可能的,但只是有一个技巧。总之,"选择"不是为这个设计的。它只在与“ToList”一起使用时执行修改,因为Linq在需要数据之前不会执行。 无论如何,最好的解决方案是使用“foreach”。在下面的代码中,你可以看到:
class Person
{
public int Age;
}
class Program
{
private static void Main(string[] args)
{
var persons = new List<Person>(new[] {new Person {Age = 20}, new Person {Age = 22}});
PrintPersons(persons);
//this doesn't work:
persons.Select(p =>
{
p.Age++;
return p;
});
PrintPersons(persons);
//with "ToList" it works
persons.Select(p =>
{
p.Age++;
return p;
}).ToList();
PrintPersons(persons);
//This is the best solution
persons.ForEach(p =>
{
p.Age++;
});
PrintPersons(persons);
Console.ReadLine();
}
private static void PrintPersons(List<Person> persons)
{
Console.WriteLine("================");
foreach (var person in persons)
{
Console.WriteLine("Age: {0}", person.Age);
;
}
}
}
在"foreach"之前,你也可以做一个linq选择…
在2020年,我使用MoreLinq管道方法。https://morelinq.github.io/2.3/ref/api/html/M_MoreLinq_MoreEnumerable_Pipe__1.htm