既存のオブジェクトで「With」キーワードを使用することはどういうわけか可能ですか?
オブジェクトに対してLINQを使用して次のことを実行したいのですが、方法が見つからないようです。
From m as Product in Me _
Select m With {.Match = m.Name.IndexOf(query)} _
Where m.Name.IndexOf(query) > 0
既存のオブジェクトで「With」キーワードを使用することはどういうわけか可能ですか?
オブジェクトに対してLINQを使用して次のことを実行したいのですが、方法が見つからないようです。
From m as Product in Me _
Select m With {.Match = m.Name.IndexOf(query)} _
Where m.Name.IndexOf(query) > 0
VB.Netでは、キーワードの2つの使用法がありますWith
。
1つ目はオブジェクトの初期化です。これは、フィールドの順列ごとに特定のコンストラクターを必要とせずに、初期化式と同じ行にオブジェクトのプロパティまたはフィールドを割り当てる手段です。
Dim x = New Product With {.Name = "Foo"}
このタイプの式は、新しいオブジェクトを作成するためにのみ使用できます。既存のものを変更するために使用することはできません。
2番目の使用法はWith
ステートメントです。これにより、オブジェクトをコンテキストに配置して、いわば多くのオブジェクトを呼び出すことができます。資格なしでそれを操作します。
With x
Console.WriteLine(.Name)
.Match = 42
End With
ただし、これらのどちらでも、既存のオブジェクトを新しいオブジェクトを作成するためのテンプレートとして使用することはできません。
いいえ。問題は、With
キーワード(ステートメントではなくオブジェクト初期化キーワード)は、新しいオブジェクトを作成した後にのみ使用できることです。
VBチームは、既存のオブジェクトで使用することの副作用はWith
あまりにも混乱するだろうと考えています。
問題について:Match
がまだのプロパティでない場合Product
、最もクリーンな解決策は、必要な出力を新しいオブジェクトにカプセル化することです。
From m as Product in Me _
Select New With {.Match = m.Name.IndexOf(query), .Product = m} _
Where m.Name.IndexOf(query) > 0
これを行う方法はありません(With
コンストラクターでのみ使用できます)。これは、linqが構築されている機能原則に違反します。具体的には、副作用が発生しないということです。
最善の策は、Matchプロパティを設定して、選択した商品に新しい商品を作成することです。
From m as Product in Me _
Where m.Name.IndexOf(query) > 0 _
Select New Product() With _
{ _
.Match = m.Name.IndexOf(query), _
...apply the rest of m's properties _
}
System.Object
ラムダを受け入れる拡張メソッドを使用すると、このような機能をかなり厳密にシミュレートできます。この回答には例がありますが、C#です。VB.NETに変換するのはおそらくそれほど難しいことではありません。