LINQ: Seleccione un objeto y cambie algunas propiedades sin crear un nuevo objeto


Usando LINQ, si quisiera realizar alguna consulta y devolver el objeto desde la consulta, pero cambiar solo algunas de las propiedades de ese objeto, ¿cómo haría esto sin crear un nuevo objeto y establecer manualmente cada propiedad? Es esto posible?

Ejemplo:

var list = from something in someList
           select x // but change one property
 174
Author: Rob Volk, 2009-04-30

10 answers

No estoy seguro de cuál es la sintaxis de la consulta. Pero aquí está el ejemplo de expresión LINQ expandida.

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

Lo que esto hace es usar un método anónimo vs y expresión. Esto le permite usar varias sentencias en una lambda. Así que puede combinar las dos operaciones de establecer la propiedad y devolver el objeto en este método algo sucinto.

 308
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-30 16:28:09

Si solo desea actualizar la propiedad en todos los elementos, entonces

someList.All(x => { x.SomeProp = "foo"; return true; })
 53
Author: Jon Spokes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-26 14:16:58

Prefiero esta. Se puede combinar con otros comandos linq.

from item in list
let xyz = item.PropertyToChange = calcValue()
select item
 26
Author: Jan Zahradník,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-21 15:43:41

No debería haber ninguna magia LINQ que te impida hacer esto. No use proyección, aunque devolverá un tipo anónimo.

User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"

Que modificará el objeto real, así como:

foreach (User u in UserCollection.Where(u => u.Id > 10)
{
    u.Property = SomeValue;
}
 17
Author: Joshua Belden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-30 16:32:58

No es posible con los operadores de consulta estándar, es una Consulta Integrada por Lenguaje, no una Actualización Integrada por Lenguaje. Pero podría ocultar su actualización en métodos de extensión.

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

Ahora puede usarlo de la siguiente manera.

cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
 8
Author: Daniel Brückner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-30 16:30:20
var item = (from something in someList
       select x).firstordefault();

Obtendría el elemento, y luego podría hacer el elemento.prop1 = 5; para cambiar la propiedad específica.

¿O desea obtener una lista de elementos de la base de datos y hacer que cambie la propiedad prop1 en cada elemento de esa lista devuelta a un valor especificado? si es así, podrías hacer esto (lo estoy haciendo en VB porque lo conozco mejor):

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

(la lista contendrá todos los elementos devueltos con sus cambios)

 0
Author: Solmead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-30 16:33:34

Dado que no encontré la respuesta aquí que considero la mejor solución, aquí a mi manera:

Usar "Select" para modificar los datos es posible, pero solo con un truco. De todos modos," Select " no está hecho para eso. Simplemente ejecuta la modificación cuando se usa con "ToList", porque Linq no se ejecuta antes de que se necesiten los datos. De todos modos, la mejor solución es usar "foreach". En el siguiente código, se puede ver:

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

Antes de "foreach", también puede hacer una selección linq...

 0
Author: Stefan R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-28 11:16:31

Si desea actualizar elementos con una cláusula Where, utilice a .Donde(...) truncará sus resultados si lo hace:

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

Puede hacer actualizaciones a elementos específicos de la lista de la siguiente manera:

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

Siempre devuelva el artículo incluso si no realiza ningún cambio. De esta manera se mantendrá en la lista.

 0
Author: Pierre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-14 08:15:31

A menudo nos encontramos con esto donde queremos incluir un valor de índice y primeros y últimos indicadores en una lista sin crear un nuevo objeto. Esto le permite conocer la posición del elemento en su lista, enumeración, etc. sin tener que modificar la clase existente y luego saber si estás en el primer elemento de la lista o en el último.

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

Simplemente puede extender cualquier clase usando:

public abstract class IteratorExtender {
    public int ListIndex { get; set; }
    public bool IsFirst { get; set; } 
    public bool IsLast { get; set; } 
}

public class Item : IteratorExtender {}
 0
Author: Informitics,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-25 13:01:29
User u = UserCollection.Single(u => u.Id == 1);
u.FirstName = "Bob"
 -3
Author: kazem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-05 03:57:49