Linq: установить свойство при выполнении проекции
Я делаю простой GroupBy, беря первый элемент, но я хочу изменить одно из свойств каждого результата.
class M
{
public string Name {get; set;}
public int NOfPeopleWithTheSameName {get; set;}
public string P1 {get; set;}
public string P2 {get; set;}
public string P3 {get; set;}
public string P4 {get; set;}
public string P5 {get; set;}
}
List<M> myList = GetMyList();
var l2 = myList
.GroupBy(m => m.Name)
.Select(group => new M { Name = group.Key, NOfPeopleWithTheSameName = group.Count() });
Это довольно просто, но этот способ не самый лучший, если класс имеет много свойств (так как каждое значение свойства должно быть скопировано в новое)? Я должен копировать их один за другим.
Я хотел бы просто взять элемент и изменить свойство NOfPeopleWithTheSameName
Ответы
Ответ 1
Вам не нужно создавать новый M
, вы можете вернуть его, например:
var l2 = myList
.GroupBy(m => m.Name)
.Select(group =>
{
var m = group.First();
m.NOfPeopleWithTheSameName = group.Count();
return m;
});
Однако, если вы собираетесь добавить свойство к своей модели только для этого, я бы предложил вместо этого использовать другой класс, который обертывает исходную модель и счетчик - не загрязняйте ваши модели. Например, у вас может быть общий класс-оболочка:
public class ModelCount<T>
{
public T Model { get; set; }
public int Count { get; set; }
}
И теперь вот так:
var l2 = myList
.GroupBy(m => m.Name)
.Select(group => new ModelCount<M>
{
Model = group.First(),
Count = group.Count()
});
Ответ 2
Да, вы можете...
class Test
{
public string Name { get; set; }
public int Number { get; set; }
}
var tests = new List<Test> { /* ... your data here ... */ };
var modifiedTests = tests.Select(test => { test.Name = "MODIFIED"; return test; });
// this actually executes above query and modifies your original items in the list:
var modifiedMaterialized = modifiedTests.ToList();
Но вы действительно, действительно (!) не должны!
LinQ - это интегрированный язык. Наличие запроса с побочными эффектами - зло. Усы скручивают зло. Просто не делайте, вы сбережете себе много боли.
Я думаю, что вы хотите просто не LinQ, а обычные циклы:
class M
{
public string Name {get; set;}
public int NOfPeopleWithTheSameName {get; set;}
public string P1 {get; set;}
public string P2 {get; set;}
public string P3 {get; set;}
public string P4 {get; set;}
public string P5 {get; set;}
}
List<M> myList = GetMyList();
var groups = myList.GroupBy(m => m.Name).ToList();
foreach(var group in groups)
{
foreach(var member in group)
{
member.NOfPeopleWithTheSameName = group.Count();
}
}