Trợ giúp về lỗi chung chung C # - "Loại 'T' phải là loại giá trị không thể nullable"


100

Tôi mới sử dụng C # và không hiểu tại sao mã sau không hoạt động.

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

Nó đưa ra lỗi sau trong quá trình biên dịch:

Kiểu 'T' phải là kiểu giá trị không thể nullable để sử dụng nó làm tham số 'T' trong kiểu hoặc phương thức chung 'System.Nullable <T>'

1
Lỗi trình biên dịch cung cấp cho bạn dòng định nghĩa hàm vì đó là nơi có lỗi.
SLaks

Câu trả lời:


180

Bạn cần thêm một T : structràng buộc:

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

Nếu không, C # sẽ cố gắng tìm ra Nullable<T>nghĩa là gì và nhận ra rằng bản thân nó chưa có ràng buộc yêu cầu Nullable<T>. Nói cách khác, bạn có thể thử gọi:

CoalesceMax<string>(...)

điều này sẽ không có ý nghĩa, vì Nullable<string>không hợp lệ.


16

Các Nullable<T>loại có một hạn chế về nó đòi hỏi Tlà một kiểu giá trị ( structtrong C #). Đó là lý do tại sao trình biên dịch cho bạn biết Nullable<T>chứ không phải hàm của bạn hoặc trang web gọi của hàm đó - chính Nullablelớp là nguyên nhân gốc rễ của lỗi, vì vậy điều này thực sự hữu ích hơn nếu trình biên dịch chỉ vào hàm của bạn và nói "cái này không ổn, sửa nó!" (Hãy tưởng tượng nếu CoalesceMaxsử dụng một số generic và vi phạm ràng buộc chỉ đối với một trong số chúng - sẽ hữu ích hơn nếu biết rằng generic nào đã bị phá vỡ ràng buộc hơn là chỉ biết rằng một hoặc nhiều ràng buộc trong CoalesceMaxđó đã bị phá vỡ).

Giải pháp là làm cho của bạn Tvà của họ Ttương thích bằng cách đưa ra cùng một ràng buộc. Điều này được thực hiện bằng cách thêm structràng buộc, ràng buộc này phải có trước tất cả giao diện / ràng buộc mới:

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

6

Phương pháp chung của bạn đang sử dụng a Nullable<T>.

Tuy nhiên, bạn không hạn chế loại T, vì vậy nó có thể kết thúc Nullable<Form>, điều này rõ ràng là không hợp lệ.

Bạn cần thay đổi ràng buộc where T : struct, IComparableđể đảm bảo rằng đó Tchỉ có thể là một kiểu giá trị.


2

Không phải là câu trả lời chính xác cho OP nhưng vì đây là điều đầu tiên xuất hiện trên google với cùng một thông báo lỗi, tôi phải thêm ràng buộc vào định nghĩa lớp của mình, thay vì phương thức của tôi, ví dụ:

public class MyClass<T> where T : struct
{
    public void MyMethod(T? value)
    {
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.