Ayrıca, C # stillerinde kullanıldığında Linq sorgusunun daha okunabilir olmasına yardımcı olmak için uzatma yöntemlerinin eklendiğini unutmayın.
Bu 2 etki kesinlikle eşdeğerdir, ancak ilki çok daha okunabilirdir (ve okunabilirlikteki boşluk elbette daha fazla yöntem zincirlendiğinde artacaktır).
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));
Tam nitelikli sözdiziminin şöyle olması gerektiğini unutmayın:
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));
Şans eseri, türü parametreleri Where
ve Last
bu iki yöntemden ilk parametre (anahtar kelimeye göre tanıtıldı parametresi varlığında sayesinde infered edilebilir olarak, açıkça belirtilmelidir gerekmezthis
ve onları uzantısı yöntemlerini olun).
Bu nokta, uzatma yöntemlerinin (diğerlerinin yanı sıra) açıkça bir avantajıdır ve yöntem zincirlemesinin dahil olduğu her benzer senaryoda bundan faydalanabilirsiniz.
Özellikle, herhangi bir alt sınıf tarafından çağrılabilen ve bu alt sınıfa (alt sınıf türü ile) güçlü bir şekilde yazılmış bir referans döndüren bir temel sınıf yöntemine sahip olduğumu bulduğum daha zarif ve ikna edici yoldur.
Örnek (tamam, bu senaryo tamamen sevimsiz): iyi bir geceden sonra, bir hayvan gözlerini açar ve sonra ağlar; her hayvan aynı şekilde gözlerini açar, oysa bir köpek havlar ve bir ördek kvağı.
public abstract class Animal
{
}
public static class AnimalExtension
{
public static TAnimal OpenTheEyes<TAnimal>(this TAnimal animal) where TAnimal : Animal
{
return animal;
}
}
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();
Donald.OpenTheEyes().Kwak();
}
}
Kavramsal OpenTheEyes
olarak bir Animal
yöntem olmalı , ancak daha sonra soyut sınıfın bir örneğini döndürecektir Animal
, bu da belirli alt sınıf yöntemlerini Bark
ya Duck
da her neyse bilmeyen . * 1 ve * 2 olarak yorumlanan 2 satır daha sonra bir derleme hatası doğurur.
Ancak genişletme yöntemleri sayesinde, "çağrıldığı alt sınıf türünü bilen bir temel yönteme" sahip olabiliriz.
Basit bir jenerik yöntemin işi başarmış olabileceğini, ancak çok daha garip bir şekilde:
public abstract class Animal
{
public TAnimal OpenTheEyes<TAnimal>() where TAnimal : Animal
{
return (TAnimal)this;
}
}
Bu sefer parametre ve dolayısıyla olası dönüş türü çıkarımı yok. Çağrı şunlardan başka bir şey olamaz:
Goofy.OpenTheEyes<Dog>().Bark();
Donald.OpenTheEyes<Duck>().Kwak();
... daha fazla zincirleme söz konusuysa kodu çok ağırlaştırabilir (özellikle tür parametresinin her zaman <Dog>
Goofy'nin satırında ve <Duck>
Donald'ın satırında olacağını bilmek ...)