また、拡張メソッドは、Linq クエリを C# スタイルで使用したときに読みやすくするために追加されたことを思い出してください。
これらの 2 つの影響は完全に同等ですが、最初の影響ははるかに読みやすくなっています (もちろん、チェーンされたメソッドが増えると、読みやすさのギャップが大きくなります)。
int n1 = new List<int> {1,2,3}.Where(i => i % 2 != 0).Last();
int n2 = Enumerable.Last(Enumerable.Where(new List<int> {1,2,3}, i => i % 2 != 0));
完全修飾構文は次のようにする必要があることに注意してください。
int n1 = new List<int> {1,2,3}.Where<int>(i => i % 2 != 0).Last<int>();
int n2 = Enumerable.Last<int>(Enumerable.Where<int>(new List<int> {1,2,3}, i => i % 2 != 0));
偶然にも、 および の型パラメーターは、これら 2 つのメソッドの最初のパラメーター (キーワードによって導入され、それらを拡張メソッドにするパラメーター) の存在のおかげで推論できるため、明示的に言及する必要はWhere
ありません。Last
this
この点は明らかに拡張メソッドの利点であり、メソッド チェーンが関係するすべての同様のシナリオでその利点を活かすことができます。
特に、任意のサブクラスから呼び出し可能な基本クラス メソッドを持ち、このサブクラスへの厳密に型指定された参照を (サブクラス型で) 返すことがわかった、より洗練された説得力のある方法です。
例(わかりました、このシナリオは完全に安っぽいです):おやすみの後、動物が目を開けて泣きます。どの動物も同じように目を開けますが、犬は吠え、アヒルは鳴き声を上げます。
public abstract class Animal
{
//some code common to all animals
}
public static class AnimalExtension
{
public static TAnimal OpenTheEyes<TAnimal>(this TAnimal animal) where TAnimal : Animal
{
//Some code to flutter one's eyelashes and then open wide
return animal; //returning a self reference to allow method chaining
}
}
public class Dog : Animal
{
public void Bark() { /* ... */ }
}
public class Duck : Animal
{
public void Kwak() { /* ... */ }
}
class Program
{
static void Main(string[] args)
{
Dog Goofy = new Dog();
Duck Donald = new Duck();
Goofy.OpenTheEyes().Bark(); //*1
Donald.OpenTheEyes().Kwak(); //*2
}
}
概念的にはメソッドでOpenTheEyes
ある必要がありAnimal
ますが、抽象クラスのインスタンスを返します。これは、やなどAnimal
の特定のサブクラスメソッドを認識していません。*1 と *2 としてコメントされた 2 行は、コンパイル エラーを発生させます。Bark
Duck
しかし、拡張メソッドのおかげで、「呼び出されたサブクラスの型を知っている基本メソッド」のようなものを持つことができます。
単純なジェネリック メソッドで作業を完了できた可能性がありますが、はるかに厄介な方法であることに注意してください。
public abstract class Animal
{
//some code common to all animals
public TAnimal OpenTheEyes<TAnimal>() where TAnimal : Animal
{
//Some code to flutter one's eyelashes and then open wide
return (TAnimal)this; //returning a self reference to allow method chaining
}
}
今回は、パラメーターがないため、戻り値の型を推測することはできません。呼び出しは次のとおりです。
Goofy.OpenTheEyes<Dog>().Bark();
Donald.OpenTheEyes<Duck>().Kwak();
...より多くのチェーンが含まれる場合、コードの重みが大きくなる可能性があります(特に、型パラメーターが常に<Dog>
グーフィーの行と<Duck>
ドナルドの行にあることを知っている...)