新しいオブジェクトを作成してすべてのプロパティを手動で設定せずに、LINQクエリ結果オブジェクトの一部のプロパティを変更したい。これは可能ですか?
例:
var list = from something in someList
select x // but change one property
新しいオブジェクトを作成してすべてのプロパティを手動で設定せずに、LINQクエリ結果オブジェクトの一部のプロパティを変更したい。これは可能ですか?
例:
var list = from something in someList
select x // but change one property
回答:
クエリ構文が何であるかわかりません。しかし、これは拡張LINQ式の例です。
var query = someList.Select(x => { x.SomeProp = "foo"; return x; })
これは、無名メソッドと式を使用することです。これにより、1つのラムダで複数のステートメントを使用できます。したがって、プロパティを設定し、オブジェクトをこのやや簡潔なメソッドに返すという2つの操作を組み合わせることができます。
ToList()
beforeを追加することでうまくいくようです。なぜそれを得るのかわからない。Entity Frameworkの場合、それでも動作しません。
すべての要素のプロパティを更新したいだけの場合
someList.All(x => { x.SomeProp = "foo"; return true; })
これを妨げるLINQの魔法はありません。プロジェクションを使用しないでください。匿名型が返されます。
User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"
これにより、実際のオブジェクトが変更されます。
foreach (User u in UserCollection.Where(u => u.Id > 10)
{
u.Property = SomeValue;
}
標準のクエリ演算子では不可能です。言語統合クエリではなく、言語統合クエリです。ただし、拡張メソッドで更新を非表示にすることができます。
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;
}
}
}
これで、次のように使用できます。
cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
UPDATE
、DELETE
、とINSERT
。だから私は意味論がこの機能を妨げるものであることを主張しません。
Where
句を使用してアイテムを更新する場合、.Where(...)を使用すると、次の場合に結果が切り捨てられます。
mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();
次のように、リスト内の特定のアイテムを更新できます。
mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();
変更しなくても、必ず返品してください。これにより、リストに保持されます。
新しいオブジェクトを作成せずに、インデックス値と最初と最後のインジケーターをリストに含めたいと思うことがよくあります。これにより、既存のクラスを変更せずに、リスト内のアイテムの位置や列挙などを確認し、リストの最初のアイテムにいるか最後のアイテムにいるかを知ることができます。
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;
}))
以下を使用することで、任意のクラスを簡単に拡張できます。
public abstract class IteratorExtender {
public int ListIndex { get; set; }
public bool IsFirst { get; set; }
public bool IsLast { get; set; }
}
public class Item : IteratorExtender {}
私がここで最善の解決策と考える答えが見つからなかったので、ここに私の方法:
「選択」を使用してデータを変更することは可能ですが、これはトリックです。とにかく、そのための「選択」はできません。データが必要になる前にLinqが実行されないため、 "ToList"と一緒に使用すると、変更が実行されます。とにかく、最善の解決策は「foreach」を使用することです。次のコードでは、次のことがわかります。
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);
;
}
}
}
「foreach」の前に、linqを選択することもできます...
var item = (from something in someList
select x).firstordefault();
を取得しitem
、item.prop1=5;
特定のプロパティを変更することができます。
または、dbからアイテムのリストを取得prop1
し、返されたリスト内の各アイテムのプロパティを指定された値に変更しますか?もしそうなら、あなたはこれを行うことができます(私はそれをよりよく知っているので、私はVBでそれをしています):
dim list = from something in someList select x
for each item in list
item.prop1=5
next
(list
変更とともに返されるすべてのアイテムが含まれます)
for each
ループを記述せずにLINQステートメントを記述する方法を求めていたと思います。
2020年にはこのMoreLinq
Pipe
方法を使用します。 https://morelinq.github.io/2.3/ref/api/html/M_MoreLinq_MoreEnumerable_Pipe__1.htm
User u = UserCollection.Single(u => u.Id == 1);
u.FirstName = "Bob"