Saya dapat menemukan artikel Microsoft Connect yang membahas masalah ini secara terperinci:
Sayangnya, perilaku ini dirancang dan tidak ada solusi mudah untuk memungkinkan penggunaan dengan tipe parameter yang mungkin berisi tipe nilai.
Jika tipe tersebut dikenal sebagai tipe referensi, kelebihan standar ditentukan pada variabel tes objek untuk kesetaraan referensi, meskipun suatu tipe dapat menentukan kelebihan kustomnya sendiri. Compiler menentukan overload mana yang digunakan berdasarkan tipe statis dari variabel (penentuannya bukan polimorfik). Oleh karena itu, jika Anda mengubah contoh untuk membatasi parameter tipe generik T ke tipe referensi yang tidak disegel (seperti Pengecualian), kompiler dapat menentukan kelebihan beban spesifik untuk digunakan dan kode berikut akan dikompilasi:
public class Test<T> where T : Exception
Jika jenisnya dikenal sebagai tipe nilai, lakukan tes kesetaraan nilai spesifik berdasarkan tipe yang tepat digunakan. Tidak ada perbandingan "default" yang baik di sini karena perbandingan referensi tidak bermakna pada tipe nilai dan kompiler tidak dapat mengetahui perbandingan nilai spesifik mana yang akan dipancarkan. Kompiler dapat memancarkan panggilan ke ValueType.Equals (Object) tetapi metode ini menggunakan refleksi dan cukup tidak efisien dibandingkan dengan perbandingan nilai tertentu. Oleh karena itu, bahkan jika Anda menentukan batasan tipe-nilai pada T, tidak ada yang masuk akal bagi kompiler untuk menghasilkan di sini:
public class Test<T> where T : struct
Dalam kasus yang Anda sajikan, di mana kompiler bahkan tidak tahu apakah T adalah tipe nilai atau referensi, maka tidak ada apa pun yang dihasilkan yang akan valid untuk semua jenis yang mungkin. Perbandingan referensi tidak akan valid untuk tipe nilai dan semacam perbandingan nilai tidak terduga untuk tipe referensi yang tidak kelebihan beban.
Inilah yang dapat Anda lakukan ...
Saya telah memvalidasi bahwa kedua metode ini berfungsi untuk perbandingan referensi dan tipe nilai umum:
object.Equals(param, default(T))
atau
EqualityComparer<T>.Default.Equals(param, default(T))
Untuk melakukan perbandingan dengan operator "==", Anda harus menggunakan salah satu metode ini:
Jika semua case T berasal dari kelas dasar yang diketahui, Anda dapat membiarkan kompiler tahu menggunakan batasan tipe generik.
public void MyMethod<T>(T myArgument) where T : MyBase
Kompiler kemudian mengenali cara menjalankan operasi MyBase
dan tidak akan melemparkan "Operator '==' tidak dapat diterapkan ke operan kesalahan tipe 'T' dan 'T'" yang Anda lihat sekarang.
Pilihan lain adalah membatasi T untuk semua jenis yang mengimplementasikan IComparable
.
public void MyMethod<T>(T myArgument) where T : IComparable
Dan kemudian gunakan CompareTo
metode yang didefinisikan oleh antarmuka IComparable .
if (myArgument?.Equals( default(T) ) != null )
.