2013-09-25 29 views
6

Theo tài liệu Constraints on Type Parameters (C# Programming Guide) nó nói, và tôi trích dẫn:Tránh các toán tử == và! = Trên các tham số kiểu generic, nhưng nó có thể so sánh với null không?

Khi áp dụng những nơi T: lớp hạn chế, tránh == và = nhà khai thác trên các tham số loại vì các nhà khai thác sẽ kiểm tra cho tham khảo! chỉ danh tính, không phải cho giá trị bình đẳng. Đây là trường hợp ngay cả nếu các toán tử này bị quá tải trong một loại được sử dụng làm đối số . Đoạn mã sau minh họa điểm này; đầu ra là sai mặc dù lớp String quá tải toán tử ==.

Với ví dụ sau:

public static void OpTest<T>(T s, T t) where T : class 
{ 
    System.Console.WriteLine(s == t); 
} 
static void Main() 
{ 
    string s1 = "target"; 
    System.Text.StringBuilder sb = new System.Text.StringBuilder("target"); 
    string s2 = sb.ToString(); 
    OpTest<string>(s1, s2); 
} 

Tuy nhiên, ReSharper (Tôi vừa mới bắt đầu sử dụng các phiên bản demo/thử nghiệm để xem nếu nó là bất kỳ giá trị với tôi) đưa ra một gợi ý/mũi để làm null-kiểm tra các thông số như sau:

public Node(T type, Index2D index2D, int f, Node<T> parent) 
{ 
    if (type == null) throw new ArgumentNullException("type"); 
    if (index2D == null) throw new ArgumentNullException("index2D"); 
    if (parent == null) throw new ArgumentNullException("parent"); 
} 

(T bị hạn chế với where T : class, new())

tôi có thể một cách an toàn theo ReSha rper mà không gặp phải vấn đề mà tài liệu C# đang cố gắng bảo tôi tránh?

Trả lời

7

Có, điều đó vẫn ổn. Tài liệu nói không so sánh hai tham số vì bạn đang so sánh tham chiếu. Mã ReSharper gợi ý chỉ là đảm bảo tài liệu tham khảo bạn đã được thông qua không phải là null để an toàn. Theo tôi, lý do chính mà tài liệu C# khuyên bạn không nên làm như vậy là vì ví dụ bạn làm == với hai chuỗi được chuyển thành T1T2 nó sẽ so sánh tham chiếu. Bất kỳ lúc nào bạn làm stringA == stringB nó sẽ thực hiện so sánh giá trị với sự quá tải trong lớp chuỗi. Nó thực sự chỉ là cảnh báo chống lại việc thực hiện các loại so sánh này vì toán tử quá tải thường được sử dụng (nếu bạn sử dụng toán tử đó trên hai kiểu được khai báo trong phạm vi cục bộ) thì không.

+0

Và nếu bạn ném chuỗi ký tự vào trong hỗn hợp, bạn sẽ nhận được kết quả không thể đoán trước. – SWeko

2

Có, thường được giả định rằng null là trường hợp đặc biệt và bạn có thể thực hiện == hoặc != trên đó. Điều này là do, một phần ít nhất, thực tế là recommendation for overriding Equals nói rằng x.Equals(null) phải là false.

Nếu bạn không có T : class hạn chế, nó sẽ là một câu chuyện khác nhau, vì bạn sẽ thấy một số hành vi có thể, bất ngờ cho struct s và nullable struct s (bạn có thể muốn làm default(T) thay vì null có).

Và nếu bạn muốn trở thành rõ ràng rằng có, bạn biết bạn đang so sánh các tài liệu tham khảo để null, bạn luôn có thể sử dụng object.ReferenceEquals(x, null) (Tôi chỉ muốn đi với ==/!=, mặc dù).

4

Tài liệu hướng dẫn cho bạn biết rằng == sẽ sử dụng so sánh tham chiếu bất kể loại thực tế của T là gì, ngay cả khi nó đã quá tải toán tử ==. Trong nhiều trường hợp, đây không phải là những gì người dùng mong đợi.

Trong trường hợp mã chia sẻ lại, nó so sánh biến thành null, mà bạn muốn làm so sánh tham chiếu, chứ không phải so sánh giá trị, vì vậy tài liệu hướng dẫn bạn là hành vi chính xác tại đây.

Bạn tuy nhiên có thể làm cho nó rõ ràng hơn một chút bằng cách viết một cái gì đó như thế này, chỉ để được rõ ràng hơn:

if(object.ReferenceEquals(type, null))//... 
7

Yes.

Chỉ thực hiện rất lạ của nhà điều hành == sẽ làm cho x == null có nghĩa là một cái gì đó khác ngoài ReferenceEquals(x, null). Nếu bạn đang sử dụng các lớp có một sự thực thi kỳ lạ như vậy, bạn có vấn đề lớn hơn nó không nhất quán khi kiểm tra null bằng cách sử dụng một đối số kiểu generic.

1

Tôi sẽ nói rằng điều này là OK.

null là đặc biệt, vì vậy bạn không thực hiện so sánh thực tế giữa hai biến tham chiếu, bạn chỉ đảm bảo rằng biến tham chiếu không phải là tham chiếu null.

So sánh điều này với, ví dụ: SQL. Ở đó bạn có một cú pháp hoàn toàn khác để so sánh (a = b) và để kiểm tra trống (a is null). Các hướng dẫn là bạn nên tránh đầu tiên, nhưng thứ hai là ok.

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