À 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
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.
Si vous voulez juste mettre à jour la propriété sur tous les éléments, alors
someList.All(x => { x.SomeProp = "foo"; return true; })
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
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;
}
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);
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.
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 {}
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)
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 ...