VBおよびC#でAction / Func / Delegates / Lambdaを使用して拡張メソッドを記述する
-
05-07-2019 - |
質問
まず、.NET 3.5の機能面/ラムダ面について頭を悩ますことができません。私はこれらの機能をLINQで毎日使用していますが、私の問題は実装を理解することと、それらが実際に何を意味するかです(Lambda?System.Func?など)
これを念頭に置いて、以下をどのように達成しますか:
例として、List(Of T)のExtensionメソッドを使用して、List内のすべてのオブジェクトのプロパティを特定の値に設定し、更新されたList(Of T)を返します。次のように呼び出されます。
VB:
Dim someList As List(Of TextBox) = (New List(Of TextBox)).UpdateExtension(Function(txtb) txtb.Text = "something")
C#:
List<TextBox> someList = (new List<TextBox>()).UpdateExtension(txtb => txtb.Text = "something");
VBとC#の両方で、拡張メソッドはどのようになりますか?
i.e:
<Extension()> _
Public Function UpdateExtension(Of T)(ByVal source As List(Of T), ByVal predicate As ??) As List(Of T)
'??
End Function
乾杯!
編集
多くの人が指摘しているように、上記は多かれ少なかれ、.ForEach()で達成できます。しかし、私の関心は.ForEach()のようなものがどのように実装されているかを理解することです。つまり、上記の問題の解決策の実装に興味があります。
解決
実際には、ここで拡張メソッドをマイキングして一致させています。ほぼSelectとForEachの組み合わせです。リストの要素を変更し、元の列挙を返すことができるメソッドが必要なようです。以下はあなたのためのトリックを行う必要があります。
VB.Net
<Extension()> _
Public Function UpdateExtension(Of T)(ByVal source As IEnumerable(Of T), ByVal del As Action(Of T)) As IEnumerable(Of T)
For Each cur in source
del(cur)
Next
Return source
End Function
C#
public static IEnumerable<T> UpdateExtension<T>(this IEnumerable<T> source, Action<T> del) {
foreach ( var cur in source ) {
del(cur);
}
return source;
}
他のヒント
新しいリストを返すのではなく、その場でリストを変更することを除いて、これは単なる .ForEach()
呼び出しです。
これがどのように機能するかを本当に理解するには、リストよりも IEnumerable
の観点から考えてください。以下の2つの式の結果が同じである理由と、後者の方が一般的に望ましい理由を考えてください:
MyEnumerable.Count() > 2
MyEnumerable.Skip(2).Any()
これを実現するには、C#の yield
キーワードを使用して、標準のIEnumerable拡張機能を再実装します。 2番目のパフォーマンスが向上した理由が本当にわかったら、調子が良いはずです。
さまざまな基本的なデリゲートタイプについては、学習する必要があります。 Func
を基本的な共通デリゲートと考えてください。ここでは、ジェネリック型パラメーターの引数の型と戻り値の型を指定します。次に、 Action
は戻り値の型がvoidである Func
の特殊なケースと考え、 Predicate
は戻り値の型がboolである特殊なケースと考えます。
拡張機能は、thisキーワードに続く最初のパラメーターとして拡張機能のターゲットを取得する静的メソッドによって、静的クラスに実装されます。あなたの例を実装するには、次のようにします。
public static class ListBoxExtensions
{
public static List<TextBox> SetToValue(this List<TextBox> txtBoxes, string sValue)
{
txtBoxes.ForEach(txtBox => txtBox.Text = sValue);
return txtBoxes;
}
}
3つのテキストボックスがあるWindowsフォームでこれを使用するには:
private void Form1_Load(object sender, EventArgs e)
{
List<TextBox> boxes = new List<TextBox>
{
textBox1,
textBox2,
textBox3
}.SetToValue("Hello");
}
申し訳ありません-VBを話さないでください。
これがお役に立てば幸いです。