Довідка з помилкою C # generics - "Тип" T "повинен бути ненульовим типом значення"


100

Я новачок у C # і не розумію, чому наступний код не працює.

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

Він дає таку помилку під час компіляції:

Тип 'T' повинен бути типом значення, яке не зводиться до нуля, щоб використовувати його як параметр 'T' у загальному типі або методі 'System.Nullable <T>'

1
Помилка компілятора дає вам рядок визначення функції, тому що саме тут є помилка.
Слакс

Відповіді:


181

Вам потрібно додати T : structобмеження:

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

В іншому випадку C # спробує розібратися, що Nullable<T>означає, і зрозуміє, що вона вже не має обмежень, необхідних для Nullable<T>себе. Іншими словами, ви можете спробувати зателефонувати:

CoalesceMax<string>(...)

що не мало б сенсу, оскільки Nullable<string>недійсне.


16

Nullable<T>Тип має обмеження на ньому , яка вимагає , Tщоб бути типом значення ( structв C #). Ось чому компілятор розповідає вам, Nullable<T>а не ваша функція або сайт виклику цієї функції - саме Nullableклас є першопричиною помилки, тому це насправді корисніше, якщо якщо компілятор просто вказав на вашу функцію і сказав "це не правильно, виправте це!" (Уявіть собі, якщо CoalesceMaxвикористовується декілька дженериків і порушує обмеження лише на одній із них - корисніше знати, у якого родового порушено обмеження, ніж просто знати, що CoalesceMaxбуло порушено одне чи більше обмежень ).

Рішення полягає в тому, щоб зробити ваше Tта їх Tсумісними шляхом введення однакового обмеження. Це робиться шляхом додавання structобмеження, яке повинно бути перед усіма інтерфейсами / новими обмеженнями:

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

6

Ваш загальний метод використовує a Nullable<T>.

Тим не менш, ви не обмежуєте тип T, тому це може виявитися Nullable<Form>недійсним.

Вам потрібно змінити обмеження, щоб where T : struct, IComparableпереконатися, що Tможе бути лише тип значення.


2

Не зовсім відповідь на ОП, але оскільки це перше, що з’явилося в Google для того ж повідомлення про помилку, мені довелося додати обмеження щодо визначення мого класу, а не мого методу, наприклад

public class MyClass<T> where T : struct
{
    public void MyMethod(T? value)
    {
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.