2010-02-09 36 views
76

Tôi mới dùng C# và không hiểu tại sao mã sau không hoạt động.Trợ giúp với lỗi C# generics - "Loại 'T' phải là loại giá trị không thể null"

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ó cung cấp cho các lỗi sau quá trình biên dịch:

Loại 'T' phải là một kiểu giá trị không nullable để sử dụng nó như là tham số 'T' trong các loại generic hoặc phương pháp hệ thống ' .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 xảy ra lỗi. – SLaks

Trả lời

144

Bạn cần phải thêm một T: hạn chế struct:

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

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

CoalesceMax<string>(...) 

không có ý nghĩa, vì Nullable<string> không hợp lệ.

4

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

Tuy nhiên, bạn không bị ràng buộc loại T, vì vậy nó có thể kết thúc là 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 thành where T : struct, IComparable để đảm bảo rằng T chỉ có thể là loại giá trị.

11

Loại Nullable<T> có ràng buộc với yêu cầu T là loại giá trị (struct trong C#). Đó là lý do tại sao trình biên dịch cho bạn biết về Nullable<T> và không phải chức năng của bạn hoặc trang web gọi hàm đó - đó là lớp Nullable là nguyên nhân gốc 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 "điều này không đúng, sửa nó!" (Hãy tưởng tượng nếu CoalesceMax sử dụng một số generics, và vi phạm ràng buộc trên chỉ một trong số họ - nó hữu ích hơn để biết generic nào có ràng buộc của nó bị hỏng hơn là chỉ biết rằng một hoặc nhiều ràng buộc trong CoalesceMax bị hỏng).

Giải pháp là làm cho T của bạn và tương thích T bằng cách giới thiệu cùng một ràng buộc. Này được thực hiện bằng cách thêm struct ràng buộc, mà phải đến trước khi tất cả các giao diện/trở ngại mới:

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

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

public class MyClass<T> where T : struct 
{ 
    public void MyMethod(T? value) 
    { 
    } 
} 
Các vấn đề liên quan