ฉันสามารถค้นหาบทความ Microsoft Connectที่กล่าวถึงปัญหานี้ในรายละเอียดบางอย่าง:
น่าเสียดายที่พฤติกรรมนี้เกิดจากการออกแบบและไม่มีวิธีแก้ปัญหาที่ง่ายในการเปิดใช้งานการใช้กับพารามิเตอร์ประเภทที่อาจมีประเภทของค่า
หากทราบว่าเป็นประเภทการอ้างอิงเกินพิกัดเริ่มต้นที่กำหนดไว้ในตัวแปรทดสอบวัตถุเพื่อความเท่าเทียมกันอ้างอิงถึงแม้ว่าประเภทอาจระบุเกินพิกัดที่กำหนดเองของตัวเอง คอมไพเลอร์จะกำหนดว่าโอเวอร์โหลดใดที่จะใช้ตามชนิดสแตติกของตัวแปร (การกำหนดไม่ใช่ polymorphic) ดังนั้นหากคุณเปลี่ยนตัวอย่างของคุณเพื่อ จำกัด พารามิเตอร์ประเภททั่วไป T เป็นประเภทอ้างอิงที่ไม่ได้ปิดผนึก (เช่นข้อยกเว้น) คอมไพเลอร์สามารถกำหนดโอเวอร์โหลดเฉพาะที่จะใช้และรหัสต่อไปนี้จะรวบรวม:
public class Test<T> where T : Exception
หากทราบว่าเป็นประเภทประเภทค่าให้ดำเนินการทดสอบความเท่าเทียมกันของค่าเฉพาะตามประเภทที่แน่นอนที่ใช้ ไม่มีการเปรียบเทียบ "เริ่มต้น" ที่ดีที่นี่เนื่องจากการเปรียบเทียบการอ้างอิงไม่มีความหมายกับประเภทค่าและคอมไพเลอร์ไม่สามารถรู้ได้ว่าการเปรียบเทียบค่าเฉพาะกับการเปล่ง คอมไพเลอร์สามารถส่งการเรียกไปยัง ValueType.Equals (Object) แต่วิธีนี้ใช้การสะท้อนและไม่มีประสิทธิภาพค่อนข้างเมื่อเทียบกับการเปรียบเทียบค่าเฉพาะ ดังนั้นแม้ว่าคุณจะต้องระบุข้อ จำกัด ประเภทค่าบน T ไม่มีอะไรที่สมเหตุสมผลสำหรับคอมไพเลอร์ที่จะสร้างที่นี่:
public class Test<T> where T : struct
ในกรณีที่คุณนำเสนอโดยที่คอมไพเลอร์ไม่ทราบว่า T เป็นค่าหรือประเภทการอ้างอิงไม่มีอะไรคล้ายกันในการสร้างที่จะถูกต้องสำหรับประเภทที่เป็นไปได้ทั้งหมด การเปรียบเทียบการอ้างอิงจะไม่ถูกต้องสำหรับประเภทค่าและการเปรียบเทียบค่าบางประเภทอาจไม่คาดคิดสำหรับประเภทการอ้างอิงที่ไม่ได้ใช้งานมากเกินไป
นี่คือสิ่งที่คุณสามารถทำได้ ...
ฉันได้ตรวจสอบแล้วว่าวิธีการทั้งสองวิธีนี้ใช้สำหรับการเปรียบเทียบการอ้างอิงและประเภทค่าทั่วไป:
object.Equals(param, default(T))
หรือ
EqualityComparer<T>.Default.Equals(param, default(T))
ในการเปรียบเทียบกับตัวดำเนินการ "==" คุณจะต้องใช้วิธีใดวิธีหนึ่งต่อไปนี้:
หากทุกกรณีของ T สืบทอดมาจากคลาสฐานที่รู้จักคุณสามารถให้คอมไพเลอร์ทราบโดยใช้ข้อ จำกัด ประเภททั่วไป
public void MyMethod<T>(T myArgument) where T : MyBase
คอมไพเลอร์ตระหนักถึงวิธีการดำเนินการ MyBase
และจะไม่โยน "Operator '==' ไม่สามารถใช้กับตัวถูกดำเนินการประเภท 'T' และ 'T'" ข้อผิดพลาดที่คุณเห็นตอนนี้
อีกตัวเลือกหนึ่งที่จะ จำกัด T ชนิดใด ๆ IComparable
ที่นำไปปฏิบัติ
public void MyMethod<T>(T myArgument) where T : IComparable
แล้วใช้CompareTo
วิธีการที่กำหนดโดยอินเตอร์เฟซ IComparable
if (myArgument?.Equals( default(T) ) != null )
รหัสของคุณจะกลายเป็น