C # generic "where constraint" กับ "any generic type"?


113

ขอยกตัวอย่าง:

  1. ฉันมีนิยามคลาส / อินเทอร์เฟซทั่วไป:

    interface IGenericCar< T > {...}

  2. ฉันมีคลาส / อินเทอร์เฟซอื่นที่ฉันต้องการเชื่อมโยงกับคลาสด้านบนเช่น:

    interface IGarrage< TCar > : where TCar: IGenericCar< (**any type here**) > {...}

โดยพื้นฐานแล้วฉันต้องการให้ IGarrage ทั่วไปของฉันขึ้นอยู่กับIGenericCarไม่ว่าจะเป็นIGenericCar<int>หรือIGenericCar<System.Color>เพราะฉันไม่มีการพึ่งพาประเภทนั้นก็ตาม

คำตอบ:


142

โดยทั่วไปมี 2 วิธีในการบรรลุเป้าหมายนี้

ทางเลือกที่ 1 : เพิ่มพารามิเตอร์อื่นเพื่อIGarrageแทนค่าTที่ควรส่งผ่านไปยังIGenericCar<T>ข้อ จำกัด :

interface IGarrage<TCar,TOther> where TCar : IGenericCar<TOther> { ... }

ตัวเลือกที่ 2 : กำหนดอินเทอร์เฟซพื้นฐานIGenericCar<T>ซึ่งไม่ใช่แบบทั่วไปและ จำกัด กับอินเทอร์เฟซนั้น

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }

6
โอเค แต่ฉันควรทำอย่างไรถ้าฉันต้องการใช้ประเภททั่วไปTในIGarage<TCar>? ฉันไม่เห็นความเป็นไปได้ใด ๆ ใน option2 ทางออกที่ดีที่สุดจะเป็นอย่างไรถ้าIGarage<TCar>พบประเภทตามประเภทของการวิเคราะห์T TCar
pt12lol

2
สำหรับคนรุ่นหลังสามารถสร้างชนิดที่มีพารามิเตอร์ type เป็นประเภท raw generic แต่ด้วยการสะท้อนที่รันไทม์เท่านั้นและไม่สามารถสร้างคลาสที่สร้างขึ้นได้เนื่องจากพารามิเตอร์ประเภท raw generic ไม่สามารถสร้างได้โดยอัตโนมัติหากไม่มีคำจำกัดความทั้งหมด ของพารามิเตอร์ประเภทตามลำดับของ ITS ฉันไม่เห็นว่าสิ่งนี้จะมีประโยชน์ตรงไหนยกเว้นในกรณีที่สมาชิกคงที่ของคลาสนอกสุด (เช่นIGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral()ซึ่งอาจเป็นผลมาจากการออกแบบที่ไม่ดี) แต่ฉันได้ทำไปแล้วในการซ่อมแซมและมัน เป็นไปได้.
Michael Hoffmann

ฉันคิดว่าทุกคนสามารถเพิ่มอินเทอร์เฟซ IGenericCar ลงในคลาสและทำลายวิธีการที่ จำกัด ด้วยคลาสที่ไม่คาดคิด
N-ate

2
@ pt12lol: หากIGarrage<TCar>จัดการกับประเภททั่วไปที่อยู่ภายใต้จริง (เช่นจัดการคุณสมบัติของประเภทดังกล่าว) จำเป็นต้องทราบประเภทซึ่งคุณต้องระบุประเภทซึ่งเป็นตัวเลือกที่ 1 (เป็นตัวเลือกเดียวที่ทำงานได้) อย่างไรก็ตามหากIGarrage<TCar>ไม่ได้จัดการกับประเภททั่วไปที่อยู่ภายใต้โดยตรง ( IGarrage<TCar>รหัสทั้งหมดไม่เชื่อเรื่องพระเจ้าของประเภทพื้นฐานนี้) ตัวเลือก 2 ก็ใช้ได้
Flater

6

มันสมเหตุสมผลไหมที่จะทำสิ่งที่ชอบ:

interface IGenericCar< T > {...}
interface IGarrage< TCar, TCarType > 
    where TCar: IGenericCar< TCarType > {...}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.