นี่คือคำถามเกี่ยวกับวิธีการขยาย C # และปรัชญาการออกแบบของพวกเขาดังนั้นฉันคิดว่าวิธีที่ดีที่สุดในการตอบคำถามนี้คือการอ้างอิงเอกสารของ MSDN เกี่ยวกับวัตถุประสงค์ของวิธีการขยาย :
วิธีการขยายช่วยให้คุณสามารถ "เพิ่ม" วิธีการประเภทที่มีอยู่โดยไม่ต้องสร้างประเภทที่ได้รับใหม่การรวบรวมใหม่หรือการปรับเปลี่ยนประเภทเดิม วิธีการขยายเป็นวิธีคงที่ชนิดพิเศษ แต่พวกเขาจะเรียกว่าราวกับว่าพวกเขาเป็นวิธีการอินสแตนซ์ในประเภทขยาย สำหรับรหัสลูกค้าที่เขียนด้วย C #, F # และ Visual Basic ไม่มีความแตกต่างที่ชัดเจนระหว่างการเรียกใช้วิธีการส่วนขยายและวิธีการที่กำหนดไว้ในประเภทจริง
...
โดยทั่วไปเราขอแนะนำให้คุณใช้วิธีการขยายอย่าง จำกัด และเฉพาะเมื่อคุณต้อง เมื่อใดก็ตามที่เป็นไปได้รหัสลูกค้าที่ต้องขยายประเภทที่มีอยู่ควรทำโดยการสร้างประเภทใหม่ที่ได้มาจากประเภทที่มีอยู่ สำหรับข้อมูลเพิ่มเติมให้ดูที่การสืบทอด
เมื่อใช้วิธีการส่วนขยายเพื่อขยายชนิดที่มีซอร์สโค้ดที่คุณไม่สามารถเปลี่ยนแปลงได้คุณจะเสี่ยงต่อการเปลี่ยนแปลงในการใช้งานชนิดนั้นจะทำให้วิธีการขยายของคุณแตก
หากคุณใช้วิธีการขยายสำหรับประเภทที่กำหนดให้จำจุดต่อไปนี้:
- วิธีการขยายจะไม่ถูกเรียกถ้ามันมีลายเซ็นเช่นเดียวกับวิธีการที่กำหนดไว้ในประเภท
- วิธีการขยายเข้ามาในขอบเขตที่ระดับเนมสเปซ ตัวอย่างเช่นถ้าคุณมีคลาสสแตติกจำนวนมากที่มีเมธอดส่วนขยายในเนมสเปซเดี่ยวที่ตั้งชื่อ
Extensions
พวกเขาทั้งหมดจะถูกนำเข้าสู่ขอบเขตโดยusing Extensions;
คำสั่ง
เพื่อสรุปวิธีการขยายได้รับการออกแบบเพื่อเพิ่มวิธีการอินสแตนซ์ให้กับประเภทเฉพาะแม้ว่านักพัฒนาไม่สามารถทำได้โดยตรง และเนื่องจากเมธอดของอินสแตนซ์จะแทนที่เมธอดส่วนขยายเสมอถ้ามี (ถ้าเรียกว่าใช้ไวยากรณ์เมธอดของอินสแตนซ์) จึงควรทำเฉพาะในกรณีที่คุณไม่สามารถเพิ่มเมธอดหรือขยายคลาสได้โดยตรง *
กล่าวอีกนัยหนึ่งวิธีการขยายควรกระทำเช่นเดียวกับวิธีการอินสแตนซ์ที่จะเพราะมันอาจจะกลายเป็นวิธีการที่ลูกค้าบางราย และเนื่องจากวิธีการอินสแตนซ์ควรโยนถ้าวัตถุที่มันถูกเรียกบนคือnull
ดังนั้นวิธีการขยายควร
* ขณะที่ทราบด้านตรงนี้เป็นสถานการณ์ที่นักออกแบบของ LINQ ที่ต้องเผชิญกับ: เมื่อ C # 3.0 ได้รับการปล่อยตัวมีอยู่นับล้านของลูกค้าที่ได้ใช้System.Collections.IEnumerable
และSystem.Collections.Generic.IEnumerable<T>
ทั้งในคอลเลกชันของพวกเขาและในforeach
ลูป ชั้นเรียนเหล่านี้กลับIEnumerator
วัตถุซึ่งมีเพียงสองวิธีCurrent
และMoveNext
เพื่อเพิ่มวิธีการเช่นใด ๆ เพิ่มเติมที่จำเป็นเช่นCount
, Any
ฯลฯ จะหมดล้านเหล่านี้ของลูกค้า ดังนั้นเพื่อให้ฟังก์ชั่นนี้ (โดยเฉพาะอย่างยิ่งเนื่องจากสามารถนำมาใช้ในแง่ของCurrent
และMoveNext
ด้วยความสะดวกสัมพัทธ์) พวกเขาปล่อยมันเป็นวิธีการขยายซึ่งสามารถนำไปใช้กับที่มีอยู่ในปัจจุบันIEnumerable
อินสแตนซ์และยังสามารถนำไปใช้กับคลาสได้ด้วยวิธีที่มีประสิทธิภาพมากขึ้น หากผู้ออกแบบของ C # ตัดสินใจที่จะเปิดตัว LINQ ในวันแรกมันจะถูกจัดเตรียมไว้เป็นวิธีการของอินสแตนซ์IEnumerable
และพวกเขาอาจจะออกแบบระบบบางประเภท