Không có câu trả lời đơn giản cho câu hỏi này. Bất cứ ai nói luôn luôn sử dụng một hoặc khác là cho bạn lời khuyên nghèo, theo ý kiến của tôi.
Có một số phương pháp khác nhau mà bạn có thể gọi để so sánh các cá thể đối tượng. Với hai trường hợp đối tượng a
và b
, bạn có thể viết:
Object.Equals(a,b)
Object.ReferenceEquals(a,b)
a.Equals(b)
a == b
tất cả Đây có thể làm những việc khác nhau!
Object.Equals(a,b)
sẽ (theo mặc định) thực hiện so sánh bình đẳng tham chiếu trên loại tham chiếu và so sánh bit trên các loại giá trị.Từ các tài liệu MSDN:
Việc thực hiện mặc định của Equals hỗ trợ bình đẳng tham khảo cho loại tài liệu tham khảo, và bình đẳng Bitwise với nhiều loại giá trị. Tham chiếu bình đẳng có nghĩa là các tham chiếu đối tượng được so sánh tham chiếu đến cùng một đối tượng. Mức độ bình đẳng bằng bit có nghĩa là các đối tượng được so sánh có cùng biểu diễn nhị phân .
Lưu ý rằng loại có nguồn gốc có thể ghi đè phương thức Bằng để thực hiện bình đẳng giá trị. Giá trị bình đẳng nghĩa là các đối tượng được so sánh có cùng giá trị nhưng khác nhau biểu thị nhị phân .
Lưu ý đoạn cuối cùng ở trên ... chúng ta sẽ thảo luận về vấn đề này sau.
Object.ReferenceEquals(a,b)
chỉ thực hiện so sánh bình đẳng tham chiếu. Nếu các loại được chuyển là các loại giá trị được đóng hộp, kết quả luôn là false
.
a.Equals(b)
gọi phương thức dụ ảo của Object
, mà loại a
có thể ghi đè lên làm gì nó muốn. Cuộc gọi được thực hiện bằng cách sử dụng công văn ảo, vì vậy mã chạy phụ thuộc vào loại thời gian chạy là a
.
a == b
gọi toán tử quá tải tĩnh của ** loại thời gian biên dịch * của a
. Nếu việc thực thi toán tử đó gọi các phương thức mẫu trên a
hoặc b
, nó cũng có thể phụ thuộc vào kiểu tham số thời gian chạy. Kể từ khi công văn được dựa trên các loại trong biểu thức, sau đây có thể mang lại kết quả khác nhau:
Frog aFrog = new Frog();
Frog bFrog = new Frog();
Animal aAnimal = aFrog;
Animal bAnimal = bFrog;
// not necessarily equal...
bool areEqualFrogs = aFrog == bFrog;
bool areEqualAnimals = aAnimal = bAnimal;
Vì vậy, vâng, có lỗ hổng để kiểm tra cho null sử dụng operator ==
. Trong thực tế, hầu hết các loại không quá tải ==
- nhưng không bao giờ có bảo đảm.
Phương pháp thể hiện Equals()
không tốt hơn ở đây. Mặc dù việc triển khai mặc định thực hiện kiểm tra tính bình đẳng tham chiếu/bitwise, nhưng có thể loại ghi đè phương thức thành viên Equals()
, trong trường hợp này, việc triển khai này sẽ được gọi. Một người dùng được cung cấp thực hiện có thể trả lại bất cứ điều gì nó muốn, ngay cả khi so sánh với null.
Nhưng phiên bản tĩnh của Object.Equals()
bạn hỏi là gì? Điều này có thể kết thúc chạy mã người dùng không? Vâng, nó chỉ ra rằng câu trả lời là CÓ. Việc thực hiện Object.Equals(a,b)
mở rộng tới một cái gì đó dọc theo dòng:
((object)a == (object)b) || (a != null && b != null && a.Equals(b))
Bạn có thể thử này cho chính mình:
class Foo {
public override bool Equals(object obj) { return true; } }
var a = new Foo();
var b = new Foo();
Console.WriteLine(Object.Equals(a,b)); // outputs "True!"
Do đó, nó có thể cho các tuyên bố: Object.Equals(a,b)
để chạy mã người dùng khi không trong số các loại cuộc gọi là null
.Lưu ý rằng Object.Equals(a,b)
không gọi phiên bản cá thể là Equals()
khi một trong hai đối số là rỗng.
Tóm lại, loại hành vi so sánh bạn nhận được có thể thay đổi đáng kể, tùy thuộc vào phương pháp bạn chọn gọi. Một bình luận ở đây, tuy nhiên: Microsoft không chính thức tài liệu hành vi nội bộ của Object.Equals(a,b)
. Nếu bạn cần một ý chí sắt bọc gaurantee so sánh một tài liệu tham khảo để null mà không bất kỳ mã chạy khác, bạn muốn Object.ReferenceEquals()
:
Object.ReferenceEquals(item, null);
Phương pháp này làm cho mục đích extremently rõ ràng - bạn đang đặc biệt chờ đợi kết quả được so sánh của hai tham chiếu cho bình đẳng tham chiếu. Lợi ích ở đây trên sử dụng một cái gì đó giống như Object.Equals(a,null)
, là nó ít có khả năng rằng ai đó sẽ đến sau cùng và nói:
"Này, đây là vụng về, chúng ta hãy thay thế nó bằng: a.Equals(null)
hoặc a == null
mà có khả năng Có thể khác nhau:
Hãy tiêm một số chủ nghĩa thực dụng ở đây, tuy nhiên Cho đến nay, chúng tôi đã nói về tiềm năng của các phương thức so sánh khác nhau để mang lại kết quả khác nhau trong khi điều này chắc chắn xảy ra. an toàn để wr ite a == null
. Các lớp .NET dựng sẵn như String
và Nullable<T>
có ngữ nghĩa được xác định rõ ràng để so sánh. Hơn nữa, chúng là sealed
- ngăn chặn bất kỳ thay đổi nào đối với hành vi của chúng thông qua kế thừa. Sau đây là khá phổ biến (và chính xác):
string s = ...
if(s == null) { ... }
Đó là không cần thiết (và xấu xí) để viết:
if(ReferenceEquals(s,null)) { ... }
Vì vậy, trong một số trường hợp hạn chế, sử dụng ==
là an toàn, và phù hợp.
Tôi nghĩ câu trả lời của tôi (câu trả lời của Microsoft bằng proxy) là một câu trả lời khá đơn giản. – mquander
Các câu hỏi như: * "tôi nên luôn luôn/không bao giờ làm X" * ngụ ý một khoảng cách kiến thức về các sắc thái của chủ đề được đề cập. Tôi cảm thấy rằng chi tiết hơn một chút sẽ hữu ích ở đây để làm rõ tại sao tôi không nghĩ một câu trả lời đơn giản là có ý nghĩa. – LBushkin
Phương thức 'object.Equals (a, b)' tĩnh có thể gọi phương thức 'Equals' quá tải/ảo trên đối tượng' a'. Nếu tôi nhớ lại chính xác, nó làm một cái gì đó như '((đối tượng) a == (đối tượng) b) || (a! = null && b! = null && a.Equals (b)) '. (Điều này là không liên quan khi so sánh với 'null', đó là những gì OP hỏi, nhưng có liên quan đến trường hợp chung.) – LukeH