2012-03-02 205 views
17

Sự khác nhau giữa ==Equals() là gì? Tôi biết rằng == được sử dụng để so sánh điều hành và phương pháp Equals() được sử dụng để so sánh nội dung của string.So tôi đã cố gắngSự khác nhau giữa toán tử == và phương thức Equals() trong C#?

// first example 
string s1 = "a"; 
string s2 = "a"; 
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2, 
          // then result will be false 

// second example 
string s1 ="a"; 
string s2 ="a"; 
Console.Write(s1 == s2);  // returns true 

Làm thế này là như vậy? Cả hai đều là các tham chiếu đối tượng khác nhau. Giả sử chúng ta xem đây là những tham chiếu. Nhưng tôi cố gắng sử dụng như thế này

string s1 = new string("ab"); 
string s2 = new string("ab"); 

Tôi nhận được biên dịch lỗi thời điểm đó không thể chuyển đổi chuỗi để char

Trả lời

21

Có một số điều đang diễn ra. Thứ nhất, trong ví dụ này:

string s1 = "a"; 
string s2 = "a"; 
Console.WriteLine(s1 == s2); 

Bạn cho rằng:

Cả hai đều là tài liệu tham khảo đối tượng khác nhau.

Điều này không đúng do thực hiện chuỗi.s1s2 là các tham chiếu đến cùng một đối tượng. Đặc tả C# đảm bảo rằng - từ mục 2.4.4.5 của đặc điểm kỹ thuật C# 4:

Khi hai hay nhiều chuỗi ký tự tương đương theo toán tử bình đẳng chuỗi (§7.10.7) xuất hiện trong cùng một chương trình, các chuỗi ký tự này tham chiếu đến cùng một cá thể chuỗi.

Vì vậy, trong trường hợp đặc biệt này, bạn sẽ vẫn nhận được "true" ngay cả khi bạn in object.ReferenceEquals(s1, s2), hoặc nếu bạn đã làm cho nó sử dụng một so sánh sắc tham khảo đúng với ==:

object s1 = "a"; 
object s2 = "a"; 
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning 

Tuy nhiên, ngay cả khi những tài liệu này tham chiếu đến các đối tượng riêng biệt, ==bị quá tải cho string. Quá tải là một quyết định biên dịch - việc triển khai sử dụng phụ thuộc vào các loại biên dịch của các toán hạng. Ví dụ:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a == b); // Uses string's implementation, prints True 

object c = a; 
object d = b; 
Console.WriteLine(c == d); // Reference identity comparison, prints False 

So sánh điều đó với object.Equals(object) là phương pháp ảo. Khi điều đó xảy ra, String quá tải phương pháp này cũng như, nhưng quan trọng là nó ghi đè lên. Vì vậy, nếu chúng ta thay đổi mã của chúng tôi để:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a.Equals((object) b)); 

object c = a; 
object d = b; 
Console.WriteLine(c.Equals(d)); 

... sau đó cả hai phương pháp gọi trong mã biên dịch sẽ chỉ đơn giản là để object.Equals(object), nhưng họ sẽ vẫn cả in Đúng vì đa hình: thực hiện trong String sẽ được sử dụng.

Đây là những gì một cuộc gọi đến quá tải phương pháp sẽ trông như thế:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string) 
+0

Hai câu hỏi: tại sao lại chọn 'd' thành' đối tượng', vì nó đã là một đối tượng? Ngoài ra, trong phần 'a Equals b', tôi sẽ gọi cả override đối tượng và chuỗi quá tải, do đó, rõ ràng hơn sự khác biệt là gì. – doekman

+0

@doekman: 1) Có, tôi không cần dàn diễn viên trong trường hợp đó. 2) Không chắc chắn những gì bạn có ý nghĩa. –

+0

Ý tôi là: xem anwer cuối cùng. Tôi đã không trực tiếp nhận được lời giải thích của bạn về quá tải/ghi đè .... – doekman

7

Trích dẫn từ tài liệu của Equals:

Việc thực hiện mặc định của Equals hỗ trợ tham chiếu bình đẳng cho các loại tham chiếu và độ cân bằng bit đối với các 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 khảo cùng một đối tượng. Độ cân bằng bitwise có nghĩa là các đối tượng được so sánh có cùng biểu diễn nhị phân.

== operator:

Đối với các loại giá trị được xác định trước, các nhà điều hành bình đẳng (==) trả về true nếu các giá trị của toán hạng của nó đều bình đẳng, false. Để tham khảo các loại khác với chuỗi, == trả về true nếu hai toán hạng của nó tham chiếu đến cùng một đối tượng. Đối với loại chuỗi, == so sánh giá trị của các chuỗi .

Trả lại câu hỏi của bạn: tại sao s1 == s2 trả về true? Chuỗi là những con thú đặc biệt trong .NET. Chúng đại diện cho các loại tham chiếu bất biến. Chúng được thực tập trong .NET. Điều này có nghĩa rằng nếu bạn có 2 hằng số chuỗi với cùng một giá trị, chúng sẽ tham chiếu đến cùng một cá thể đối tượng khi chạy.

Trích từ documentation:

Phổ biến runtime ngôn ngữ bảo tồn lưu trữ chuỗi bằng cách duy trì một bảng , được gọi là hồ sinh nội trú, có chứa một tham chiếu duy nhất để mỗi chuỗi chữ độc đáo tuyên bố hoặc tạo lập trình trong chương trình của bạn. Do đó, một thể hiện của một chuỗi ký tự bằng một giá trị cụ thể là chỉ tồn tại một lần trong hệ thống.

+0

Nó không * chỉ * do thực tập. Interning là lý do tại sao nó sẽ hoạt động ngay cả khi chúng được khai báo là kiểu 'object'. Nhưng ngay cả các tham chiếu đến các đối tượng chuỗi riêng biệt có cùng nội dung sẽ hoạt động miễn là các loại biên dịch có liên quan là cả hai chuỗi, do quá tải toán tử. Các tài liệu bạn đã trích dẫn là gây hiểu nhầm vì nó cho thấy có một số xử lý đặc biệt * chỉ cho chuỗi * - không có, nó chỉ là chuỗi là * a * loại tham chiếu mà quá tải toán tử ==. –

+1

Cũng lưu ý rằng việc thực tập là một chi tiết ngôn ngữ -.NET cung cấp các cơ chế, nhưng nó sẽ là khá tốt có thể có một ngôn ngữ Dumb # đó là giống như C# trong mọi cách, ngoại trừ không có chuỗi liên tục interning. –

2

Bạn đang nghĩ dường như Java-esque. Trong java, toán tử == không thể được tùy chỉnh, vì vậy đối với các kiểu tham chiếu, nó luôn có nghĩa là bình đẳng tham chiếu, trong khi nó có nghĩa là bình đẳng giá trị cho các kiểu nguyên thủy. Mặt khác, Equals là để kiểm tra bình đẳng giá trị trong các loại tham chiếu.

Mọi thứ khác nhau trong C#. Cả hai Equals== đều có thể triển khai tùy chỉnh. Sự khác biệt là Equals là một phương pháp ảo (ví dụ), trong khi operator== là một phương pháp tĩnh. Bên cạnh đó, họ có thể cư xử một cách chính xác theo cùng một cách.

Theo mặc định, cả hai Equals== kiểm tra tính bình đẳng tham chiếu cho các loại tham chiếu và bình đẳng giá trị cho các loại giá trị. Tuy nhiên, đối với string, cả hai đều được tùy chỉnh để kiểm tra giá trị bình đẳng.

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