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();
    }
}