โปรดจำไว้ว่ามีการเพิ่มวิธีการส่วนขยายเพื่อช่วยให้การสืบค้น 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));
โดยบังเอิญพารามิเตอร์ประเภทของWhere
และLast
ไม่จำเป็นต้องกล่าวถึงอย่างชัดเจนเนื่องจากสามารถอนุมานได้เนื่องจากมีพารามิเตอร์แรกของสองวิธีนี้ (พารามิเตอร์ที่คำหลักแนะนำthis
และทำให้เป็นวิธีการขยาย)
เห็นได้ชัดว่าประเด็นนี้เป็นข้อได้เปรียบ (ในหมู่คนอื่น ๆ ) ของวิธีการขยายและคุณสามารถใช้ประโยชน์จากมันได้ในทุกสถานการณ์ที่คล้ายคลึงกันซึ่งเกี่ยวข้องกับวิธีการผูกมัด
โดยเฉพาะอย่างยิ่งมันเป็นวิธีที่สง่างามและน่าเชื่อถือกว่าที่ฉันพบว่ามีเมธอดคลาสพื้นฐานที่เรียกใช้โดยคลาสย่อยใด ๆ และส่งคืนการอ้างอิงที่พิมพ์อย่างรุนแรงไปยังคลาสย่อยนี้ (ด้วยประเภทคลาสย่อย)
ตัวอย่าง (โอเคสถานการณ์นี้ช่างวิเศษสุด ๆ ): หลังจากหลับฝันดีสัตว์ชนิดหนึ่งลืมตาแล้วส่งเสียงร้อง สัตว์ทุกตัวลืมตาเหมือนกันในขณะที่สุนัขเห่าและเป็ดกวัก
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();
}
}
แนวคิดOpenTheEyes
ควรจะเป็นAnimal
วิธีการ แต่มันก็จะกลับมาอินสแตนซ์ของระดับนามธรรมAnimal
ซึ่งไม่ทราบวิธีการที่เฉพาะเจาะจงเช่น subclass Bark
หรือDuck
หรืออะไรก็ตาม 2 บรรทัดที่แสดงความคิดเห็นเป็น * 1 และ * 2 จะทำให้เกิดข้อผิดพลาดในการคอมไพล์
แต่ด้วยวิธีการขยายเราสามารถมี "เมธอดพื้นฐานที่รู้ประเภทคลาสย่อยที่เรียกว่า"
โปรดทราบว่าวิธีการทั่วไปง่ายๆสามารถทำงานได้ แต่ในวิธีที่น่าอึดอัดใจกว่า:
public abstract class Animal
{
public TAnimal OpenTheEyes<TAnimal>() where TAnimal : Animal
{
return (TAnimal)this;
}
}
คราวนี้ไม่มีพารามิเตอร์จึงไม่มีการอนุมานประเภทการส่งคืนที่เป็นไปได้ การโทรจะเป็นอะไรไปไม่ได้นอกจาก:
Goofy.OpenTheEyes<Dog>().Bark();
Donald.OpenTheEyes<Duck>().Kwak();
... ซึ่งสามารถชั่งน้ำหนักรหัสได้มากหากมีการผูกมัดมากขึ้น (โดยเฉพาะอย่างยิ่งเมื่อรู้ว่าพารามิเตอร์ type จะอยู่<Dog>
ในบรรทัดของ Goofy และ<Duck>
ของ Donald ... )