J'ai une liste que je veux mettre à jour avec LINQ.
class Student
{
private string name;
private int marks;
public string Name { get; set;}
public int Marks { get; set; }
public Student(string name, int marks)
{
Name = name;
Marks = marks;
}
}
List<Student> myList = new List<Student>();
myList.Add(new Student("John", 10));
myList.Add(new Student("Tom", 20));
Maintenant, je veux mettre à jour la liste en utilisant LINQ de telle sorte que seules les marques de John soient mises à jour. J'utilise la syntaxe suivante:
myList.Where(w => w.Name == "Tom").Select(w=> { w.Marks = 35; return w});
Mais cela ne met pas à jour les données dans myList. Quelqu'un peut-il me dire où je me trompe?.
LINQ sert à interroger et non à mettre à jour les données. Utilisez LINQ pour obtenir les éléments que vous souhaitez modifier, puis modifiez-les dans une boucle foreach
:
foreach ( var tom in myList.Where(w => w.Name == "Tom")) {
tom.Marks = 35;
}
Comme d'autres l'ont souligné, LINQ sert à interroger des données, pas à effectuer des mises à jour.
Vous devriez itérer votre liste et modifier vos valeurs comme:
foreach (var student in myList)
{
if (student.Name == "Tom")
{
student.Marks = 35;
}
}
Ou
foreach (var student in myList.Where(r => r.Name == "Tom"))
{
student.Marks = 35;
}
Quoi que vous pensiez mieux traduit l'intention utilisée.
mais voici une chose intéressante:
Si vous avez une déclaration comme:
myList.Where(w => w.Name == "Tom").Select(w => w.Marks = 35).ToList();
Sans affecter le résultat à myList
, la requête ci-dessus modifiera la valeur dans la liste d'origine. Souvenez-vous que c’est un effet secondaire et que ce n’est pas le approprié moyen de mettre à jour . Cette modification peut être expliquée par le paramètre de référence transmis à une méthode et y étant modifié. Mais surtout, cela devrait toujours être évité . C'est une mauvaise pratique et pourrait conduire à un code vraiment déroutant. Utilisez LINQ pour interroger uniquement.
Essayer:
myList .Where(w=> w.Name == "dTomi").ToList().ForEach(i => i.Marks = 35);
Les objets sont stockés par référence dans la liste afin que vous puissiez récupérer un objet via linq puis le modifier, il reflétera les modifications apportées à la liste.
Exemple
static void Main(string[] args)
{
List<Entity> testList = new List<Entity>()
{
new Entity() {Id = 1, Text = "Text"},
new Entity() {Id = 2, Text = "Text2"}
};
Console.WriteLine($"First text value:{testList[1].Text}");
Entity entityToEdit = testList.FirstOrDefault(e => e.Id == 2);
if (entityToEdit != null)
entityToEdit.Text = "Hello You!!";
Console.WriteLine($"Edited text value:{testList[1].Text}");
Console.ReadLine();
}
internal class Entity
{
public int Id { get; set; }
public String Text { get; set; }
}
En testant l'application, vous obtiendrez le résultat suivant:
Première valeur textuelle: Text2
Valeur du texte édité: Hello You !!
que diriez-vous de la bonne vieille boucle for
for(int i = 0; i < myList.Count; i++)
if (myList[i].Name == "Tom")
{
myList[i].Marks = 35;
break;
}
bien @dasblinkenlight code devrait fonctionner, mais vous pouvez également essayer quelque chose comme ça
var query = from x in list
where x.Name = yourcondition
select new { x };
foreach(var item in query)
item.x.FieldToUpdate = SetValue;
C'est un peu maladroit, mais cela fonctionne et ne dépend pas de la transmission d'une référence. Il crée une nouvelle liste basée sur l'ancien.
var myList=myList.Select(l=>new Student {
l.Name,
Marks=l.Name=="Tom"?35:l.Marks}).ToList();
Ou plus bête:
var myList=myList.Where(l=>l.Name!="Tom").Union(
myList.Where(l=>l.Name=="Tom").Select(l=>new Student {
l.Name,
Marks=35})).ToList();
Ci-dessus peut être atteint en attribuant simplement la valeur à la collection
myList = myList
.Where(w => w.Name == "Tom")
.Select(w=> { w.Marks = 35; return w})
.ToList();