Bantuan dengan kesalahan umum C # - "Jenis 'T' harus berupa jenis nilai yang tidak dapat dinihilkan"

100

Saya baru mengenal C # dan tidak mengerti mengapa kode berikut tidak berfungsi.

public static Nullable<T> CoalesceMax<T>(Nullable<T> a, Nullable<T> b) where T : IComparable
{
    if (a.HasValue && b.HasValue)
        return a.Value.CompareTo(b.Value) < 0 ? b : a;
    else if (a.HasValue)
        return a;
    else
        return b;
}

// Sample usage:
public DateTime? CalculateDate(DataRow row)
{
    DateTime? result = null;
    if (!(row["EXPIRATION_DATE"] is DBNull))
        result = DateTime.Parse((string)row["EXPIRATION_DATE"]);
    if (!(row["SHIPPING_DATE"] is DBNull))
        result = CoalesceMax(
            result
            DateTime.Parse((string)row["SHIPPING_DATE"]).AddYears(1));
    // etc.
    return result;
}

Ini memberikan kesalahan berikut selama kompilasi:

Jenis 'T' harus berupa jenis nilai yang tidak dapat dinolkan untuk menggunakannya sebagai parameter 'T' dalam jenis umum atau metode 'System.Nullable <T>'
Josh Kelley
sumber
1
Kesalahan kompilator memberi Anda baris definisi fungsi karena di situlah letak kesalahan.
SLaks

Jawaban:

181

Anda perlu menambahkan T : structbatasan:

public static Nullable<T> CoalesceMax<T>
    (Nullable<T> a, Nullable<T> b) where T : struct, IComparable

Jika tidak, C # akan mencoba mencari tahu apa Nullable<T>artinya, dan menyadari bahwa ia belum memiliki batasan yang dibutuhkan dengan Nullable<T>sendirinya. Dengan kata lain, Anda dapat mencoba menelepon:

CoalesceMax<string>(...)

yang tidak masuk akal, karena Nullable<string>tidak valid.

Jon Skeet
sumber
16

The Nullable<T>jenis memiliki kendala di atasnya yang membutuhkan Tuntuk menjadi tipe nilai ( structdalam C #). Itulah mengapa kompilator memberi tahu Anda tentang Nullable<T>dan bukan fungsi Anda atau situs panggilan dari fungsi itu - Nullablekelaslah yang menjadi akar penyebab kesalahan, jadi ini sebenarnya lebih membantu jika kompilator hanya menunjuk ke fungsi Anda dan berkata "ini tidak benar, perbaiki!" (Bayangkan jika CoalesceMaxmenggunakan beberapa obat generik, dan melanggar batasan hanya pada salah satunya - lebih berguna untuk mengetahui generik mana yang batasannya rusak daripada hanya mengetahui bahwa satu atau lebih batasan di CoalesceMaxrusak).

Solusinya adalah membuat Anda Tdan mereka Tkompatibel dengan memperkenalkan batasan yang sama. Ini dilakukan dengan menambahkan structbatasan, yang harus ada sebelum semua antarmuka / batasan baru:

public static Nullable<T> CoalesceMax<T>(Nullable<T> a, Nullable<T> b) where T : struct, IComparable{
  ...
}

sumber
6

Metode umum Anda menggunakan file Nullable<T>.

Namun, Anda tidak membatasi jenisnya T, jadi itu bisa berakhir Nullable<Form>, yang jelas tidak valid.

Anda perlu mengubah batasan where T : struct, IComparableuntuk memastikan bahwa Thanya bisa menjadi tipe nilai.

SLaks
sumber
2

Bukan jawaban yang tepat untuk OP tetapi karena ini adalah hal pertama yang muncul di google untuk pesan kesalahan yang sama, saya harus menambahkan batasan pada definisi kelas saya, daripada metode saya, misalnya

public class MyClass<T> where T : struct
{
    public void MyMethod(T? value)
    {
    }
}
3-14159265358979323846264
sumber