LINQ: выберите объект и измените некоторые свойства, не создавая новый объект - PullRequest
189 голосов
/ 30 апреля 2009

Используя LINQ, если я хотел выполнить какой-либо запрос и вернуть объект из запроса, но изменить только некоторые свойства этого объекта, как бы я сделал это, не создавая новый объект и не устанавливая вручную каждое свойство? Возможно ли это?

Пример:

var list = from something in someList
           select x // but change one property

Ответы [ 10 ]

341 голосов
/ 30 апреля 2009

Я не уверен, что синтаксис запроса. Но вот расширенный пример выражения LINQ.

var query = someList.Select(x => { x.SomeProp = "foo"; return x; })

Для этого используется анонимный метод против и выражение. Это позволяет использовать несколько операторов в одной лямбде. Таким образом, вы можете объединить две операции установки свойства и возврата объекта в этот несколько лаконичный метод.

54 голосов
/ 12 июня 2009

Если вы просто хотите обновить свойство для всех элементов, тогда

someList.All(x => { x.SomeProp = "foo"; return true; })
29 голосов
/ 21 марта 2013

Я предпочитаю этот. Его можно комбинировать с другими командами linq.

from item in list
let xyz = item.PropertyToChange = calcValue()
select item
19 голосов
/ 30 апреля 2009

Не должно быть никакой магии 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;
}
9 голосов
/ 30 апреля 2009

Это невозможно для стандартных операторов запросов - это встроенный запрос языка, а не встроенное обновление языка. Но вы можете скрыть свое обновление в методах расширения.

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);
2 голосов
/ 14 июня 2018

Если вы хотите обновить элементы с предложением Where, использование .Where (...) будет обрезать ваши результаты, если вы сделаете:

mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();

Вы можете обновлять определенные элементы в списке следующим образом:

mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();

Всегда возвращайте товар, даже если вы не вносите никаких изменений. Таким образом, он будет сохранен в списке.

0 голосов
/ 25 августа 2018

Мы часто сталкиваемся с этим, когда мы хотим включить значение индекса, а также первый и последний показатели в список без создания нового объекта. Это позволяет вам узнать положение элемента в вашем списке, перечислении и т. Д. Без необходимости изменять существующий класс, а затем узнавать, находится ли вы у первого элемента в списке или у последнего.

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 {}
0 голосов
/ 28 августа 2015

Так как я не нашел здесь ответа, который считаю лучшим решением, вот мой путь:

Использование «Выбрать» для изменения данных возможно, но только с помощью хитрости. В любом случае, «Выбор» не предназначен для этого. Он просто выполняет модификацию при использовании с «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 ...

0 голосов
/ 05 сентября 2012
User u = UserCollection.Single(u => u.Id == 1);
u.FirstName = "Bob"
0 голосов
/ 30 апреля 2009
var item = (from something in someList
       select x).firstordefault();

Получит item, а затем вы можете сделать item.prop1=5;, чтобы изменить определенное свойство.

Или вы хотите получить список элементов из БД и попросить его изменить свойство prop1 для каждого элемента в этом возвращенном списке на указанное значение? Если это так, вы могли бы сделать это (я делаю это в VB, потому что я знаю это лучше):

dim list = from something in someList select x
for each item in list
    item.prop1=5
next

(list будет содержать все элементы, возвращенные с вашими изменениями)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...