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));
次に、Johnのマークだけが更新されるように、LINQを使用してリストを更新します。次の構文を使用しています。
myList.Where(w => w.Name == "Tom").Select(w=> { w.Marks = 35; return w});
しかし、これはmyListのデータを更新しません。誰かがどこで間違っているのか教えてもらえますか?.
LINQはクエリ用であり、データの更新用ではありません。 LINQを使用して変更するアイテムを取得し、foreach
ループでそれらを変更します。
foreach ( var tom in myList.Where(w => w.Name == "Tom")) {
tom.Marks = 35;
}
他の人が指摘したように、LINQはデータをクエリするためのものであり、更新を行うためのものではありません。
リストを反復して、次のように値を変更する必要があります。
foreach (var student in myList)
{
if (student.Name == "Tom")
{
student.Marks = 35;
}
}
または
foreach (var student in myList.Where(r => r.Name == "Tom"))
{
student.Marks = 35;
}
あなたがより良いと思うものは何でもそれを使用する意図を伝えます。
しかし、ここに興味深いものがあります:
次のようなステートメントがある場合:
myList.Where(w => w.Name == "Tom").Select(w => w.Marks = 35).ToList();
結果をmyList
に割り当てない場合、上記のクエリは元のリストの値を変更します。 覚えておいてください、これは副作用であり、proper更新する方法ではありません。これは、参照パラメーターがメソッドに渡されてそこで変更されることで説明できます。 しかし重要なことに、これは常に避けられるべきです。これは悪い習慣であり、コードを本当に混乱させる可能性があります。クエリのみにLINQを使用します。
試してください:
myList .Where(w=> w.Name == "dTomi").ToList().ForEach(i => i.Marks = 35);
上記は、コレクションに値を割り当てるだけで実現できます。
myList = myList
.Where(w => w.Name == "Tom")
.Select(w=> { w.Marks = 35; return w})
.ToList();
オブジェクトは参照によってリストに保存されるので、linqを介してオブジェクトを回復してから編集でき、リストの変更が反映されます。
例
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; }
}
アプリをテストすると、次の結果が得られます。
最初のテキスト値:Text2
編集されたテキスト値:Hello You !!
古き良きfor
ループはどうですか
for(int i = 0; i < myList.Count; i++)
if (myList[i].Name == "Tom")
{
myList[i].Marks = 35;
break;
}
よく@dasblinkenlightコードは動作するはずですが、このようなものを試すこともできます
var query = from x in list
where x.Name = yourcondition
select new { x };
foreach(var item in query)
item.x.FieldToUpdate = SetValue;
これはちょっと不格好ですが、機能し、参照が渡されることに依存しません。古いものに基づいて新しいリストを作成します。
var myList=myList.Select(l=>new Student {
l.Name,
Marks=l.Name=="Tom"?35:l.Marks}).ToList();
またはもっとばかげた:
var myList=myList.Where(l=>l.Name!="Tom").Union(
myList.Where(l=>l.Name=="Tom").Select(l=>new Student {
l.Name,
Marks=35})).ToList();