web-dev-qa-db-fra.com

LINQ: sélectionne un objet et modifie certaines propriétés sans créer de nouvel objet

À l'aide de LINQ, si je souhaitais effectuer une requête et renvoyer l'objet à partir de la requête, mais ne modifier que certaines propriétés de cet objet, comment procéder sans créer un nouvel objet et définir manuellement chaque propriété? Est-ce possible?

Exemple:

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

Je ne suis pas sûr de la syntaxe de la requête. Mais voici l’exemple d’expression LINQ développé.

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

Cela utilise une méthode anonyme vs et une expression. Cela vous permet d'utiliser plusieurs instructions dans un seul lambda. Vous pouvez donc combiner les deux opérations de définition de la propriété et de retour de l'objet dans cette méthode plutôt succincte.

326
JaredPar

Si vous voulez juste mettre à jour la propriété sur tous les éléments, alors 

someList.All(x => { x.SomeProp = "foo"; return true; })
52
Jon Spokes

Je préfère celle-ci. Il peut être combiné avec d'autres commandes linq.

from item in list
let xyz = item.PropertyToChange = calcValue()
select item
27
Jan Zahradník

Aucune magie LINQ ne devrait vous empêcher de le faire. N'utilisez pas de projection bien que cela retourne un type anonyme.

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

Cela modifiera l'objet réel, ainsi que:

foreach (User u in UserCollection.Where(u => u.Id > 10)
{
    u.Property = SomeValue;
}
19
Joshua Belden

Cela n’est pas possible avec les opérateurs de requête standard - c’est une requête intégrée dans la langue, pas une mise à jour intégrée de la langue. Mais vous pouvez cacher votre mise à jour dans les méthodes d'extension.

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

Maintenant, vous pouvez l'utiliser comme suit.

cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
9
Daniel Brückner

Si vous souhaitez mettre à jour des éléments avec une clause Where, utilisez un .Where (...) tronquera vos résultats si vous le faites:

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

Vous pouvez effectuer des mises à jour d'éléments spécifiques dans la liste, comme suit:

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

Toujours retourner l'article même si vous n'apportez aucune modification. De cette façon, il sera conservé dans la liste.

2
Pierre

Nous rencontrons souvent ceci où nous voulons inclure une valeur d'index et des premier et dernier indicateurs dans une liste sans créer un nouvel objet. Cela vous permet de connaître la position de l'élément dans votre liste, énumération, etc. sans avoir à modifier la classe existante et à savoir si vous êtes au premier ou au dernier élément de la liste.

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

Vous pouvez simplement étendre n'importe quelle classe en utilisant:

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

public class Item : IteratorExtender {}
0
Informitics
var item = (from something in someList
       select x).firstordefault();

Obtenez la item, puis vous pourriez faire item.prop1=5; pour changer la propriété spécifique.

Ou voulez-vous obtenir une liste d'éléments de la base de données et lui demander de modifier la propriété prop1 de chaque élément de cette liste renvoyée en une valeur spécifiée? Si vous pouviez le faire (je le fais dans VB parce que je le connais mieux):

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

(list contiendra tous les éléments renvoyés avec vos modifications)

0
Solmead

Comme je n’ai pas trouvé la réponse que j’estime être la meilleure solution, voici mon chemin:

Utiliser "Select" pour modifier les données est possible, mais avec une astuce. Quoi qu'il en soit, "Select" n'est pas fait pour ça. Il n’exécute que la modification lorsqu’il est utilisé avec "ToList", car Linq ne s’exécute pas avant que les données ne soient nécessaires ..__ De toute façon, la meilleure solution est d'utiliser "foreach". Dans le code suivant, vous pouvez voir:

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

Avant "foreach", vous pouvez également faire une sélection linq ... 

0
Stefan R.