C # genel hatalarıyla ilgili yardım - "'T' türü, boş değer atanamayan bir değer türü olmalıdır"


100

C # konusunda yeniyim ve aşağıdaki kodun neden çalışmadığını anlamıyorum.

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;
}

Derleme sırasında şu hatayı verir:

'T' türü, genel tür veya 'System.Nullable <T>' yönteminde 'T' parametresi olarak kullanmak için null yapılamayan bir değer türü olmalıdır

1
Derleyici hatası size işlev tanımının satırını verir çünkü hatanın olduğu yer burasıdır.
SLaks

Yanıtlar:


181

Bir T : structkısıtlama eklemeniz gerekiyor :

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

Aksi takdirde C # ne Nullable<T>anlama geldiğini anlamaya çalışacak ve Nullable<T>kendisinin gerektirdiği kısıtlamaya zaten sahip olmadığını anlayacaktır . Başka bir deyişle, aramayı deneyebilirsiniz:

CoalesceMax<string>(...)

bu mantıklı Nullable<string>değil, çünkü geçerli değil.


C # 8 Null yapılamaz bayrağı ile ne olacak?
kirin nee

1
@kirinnee: Hayır, çünkü yalnızca null yapılamayan herhangi bir tür değil, Nullable<T>yine Tde null yapılamayan bir değer türü olması gerekir.
Jon Skeet

16

Nullable<T>Tipi gerektiren üzerinde bir sınırlama vardır T(bir değer türü olması structC #). Bu nedenle derleyici Nullable<T>size işlevinizden veya bu işlevin çağrı sitesinden bahsetmiyor - Nullablehatanın temel nedeni olan sınıftır, bu nedenle bu aslında daha yararlıdır ki derleyici işlevinizi göstermiş ve "bu doğru değil, düzelt!" ( CoalesceMaxBirkaç jenerik kullandığınızı ve bunlardan yalnızca birindeki kısıtlamayı ihlal ettiğinizi düşünün - hangi jenerik kısıtlamasının kırıldığını bilmek, bir veya daha fazla kısıtlamanın ihlal edildiğini bilmekten daha yararlıdır CoalesceMax).

Çözüm, aynı kısıtlamayı getirerek sizin Tve onların Tuyumlu olmasını sağlamaktır . Bu, structtüm arayüz / yeni kısıtlamalardan önce gelmesi gereken kısıtlama eklenerek yapılır :

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

6

Genel yönteminiz bir Nullable<T>.

Bununla birlikte, türünü kısıtlamıyorsunuz T, bu yüzden sonuçta var olabilir Nullable<Form>, ki bu açıkça geçersizdir.

Bunun yalnızca bir değer türü olabileceğinden where T : struct, IComparableemin olmak için kısıtlamayı değiştirmeniz gerekir T.


2

Tam olarak OP'ye bir cevap değil, ancak aynı hata mesajı için Google'da açılan ilk şey bu olduğundan, yöntemim yerine sınıf tanımıma kısıtlamayı eklemek zorunda kaldım, örn.

public class MyClass<T> where T : struct
{
    public void MyMethod(T? value)
    {
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.