2010-09-03 22 views
8

Tôi chỉ gặp tình huống này và tôi nghĩ đó là cơ hội tốt để sử dụng từ khóa mặc định. Nhưng nó không biên dịch và tôi không thể nghĩ tại sao. Ví dụ dưới đây minh họa vấn đề của tôi:So sánh loại chung với giá trị mặc định của nó, không có giới hạn lớp chung, cung cấp lỗi biên dịch

public class Test<TDataSource> 
{ 
    public IQueryable<TDataSource> DataSource { get; set; } 

    public bool GetOneOrDefaultResult() 
    { 
     var result = DataSource.SingleOrDefault(); 
     return result != default(TDataSource); 
    } 
} 

Bạn sẽ nhận được một lỗi trên dòng 8 (" '==' điều hành có thể không được áp dụng cho toán hạng của loại 'TDataSource' và 'TDataSource'."). Tôi nghĩ rằng việc sử dụng từ khóa mặc định sẽ loại bỏ bất kỳ vấn đề so sánh nào giữa các loại tham chiếu và loại giá trị.

Thêm ràng buộc chung hạn chế TDataSource vào loại tham chiếu làm cho đoạn mã này biên dịch.

Ai đó có thể giải thích tại sao trình biên dịch sẽ không khắc phục điều này cho tôi? Nó chỉ là không đủ thông minh để thấy điều này sẽ làm việc?

này liên quan: Can't operator == be applied to generic types in C#?

[Chỉnh sửa] SLaks câu trả lời cho tôi một số nguồn cảm hứng, các '==' nhà điều hành sẽ không làm việc, nhưng Equals chức năng nên.

public class Test<TDataSource> 
{ 
    public IQueryable<TDataSource> DataSource { get; set; } 

    public bool GetOneOrDefaultResult() 
    { 
     var result = DataSource.SingleOrDefault(); 
     return result.Equals(default(TDataSource)); 
    } 
} 

Biên dịch này có hoạt động chính xác không?

+0

Nếu bạn đang cố gắng tìm ra nếu có kết quả, bạn đang làm sai bởi vì bạn sẽ không thể biết sự khác biệt giữa kết quả và kết quả là 0, – Gabe

+0

Gabe logic của chức năng chỉ là một ví dụ, nó không hữu ích. – JJoos

+1

Chỉnh sửa của bạn có thể ném NullReferenceExeption. Bạn cần gọi phương thức 'Equals (a, b)' tĩnh. – SLaks

Trả lời

5

Bạn không thể giả định rằng mọi loại giá trị sẽ ghi đè toán tử ==. (Và ngay cả khi họ đã làm, thì sẽ không có cách nào để gọi nó là sử dụng Generics; đó là một phương pháp tĩnh)

Thay vào đó, bạn nên viết

return !(ReferenceEquals((object)result, (object)default(TDataSource)) 
      || result.Equals(default(TDataSource))); 

Nếu resultnull (và một loại tài liệu tham khảo), cuộc gọi ReferenceEquals sẽ trả lại true, vì vậy Equals sẽ không được gọi và sẽ không ném một số NullReferenceException.
Nếu TDataSource là loại giá trị, thì ReferenceEquals sẽ so sánh hai tham chiếu được đóng hộp khác nhau (có thể chứa cùng một giá trị nhưng vẫn khác nhau), vì vậy nó sẽ chuyển sang cuộc gọi Equals.

+0

Lưu ý nói chung, đây là cách bạn phải so sánh hai giá trị của loại không xác định cho bình đẳng. (tức là điều này không chỉ áp dụng để tìm kiếm các giá trị mặc định) – Gabe

+0

Bạn hoàn toàn đúng. Đây có phải là cấu trúc do người dùng chỉ định không ghi đè toán tử '==' không? – JJoos

+0

@JJoos, nếu các kiểu giá trị ghi đè toán tử '==', nó được coi là thực hành tốt nhất để ghi đè 'Equals()' để nó hoạt động tương đương. Điều này không được bảo đảm nghiêm ngặt, nhưng tôi sẽ coi đó là một lỗi nếu tôi tìm thấy một loại giá trị không hoạt động theo cách này. –

Các vấn đề liên quan