Chênh lệch C # giữa == và Bằng ()


548

Tôi có một điều kiện trong một ứng dụng silverlight so sánh 2 chuỗi, vì một số lý do khi tôi sử dụng ==nó trả về false trong khi .Equals()trả về true .

Đây là mã:

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
    // Execute code
}

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}

Bất kỳ lý do như tại sao điều này đang xảy ra?



8
Ghi đè chuỗi ==, nhưng toán tử không phải là đa hình. Trong mã này, ==toán tử được gọi trên kiểu object, so sánh danh tính thay vì giá trị.
Drew Noakes

12
Để mở rộng nhận xét của @DrewNoakes: Trình biên dịch chọn ==quá tải dựa trên loại thời gian biên dịch của toán hạng. Tài Contentsản là object. Các toán tử không phải là ảo, do đó, việc thực hiện mặc định ==được gọi, đưa ra một so sánh đẳng thức tham chiếu. Với Equals, cuộc gọi chuyển sang phương thức ảo object.Equals(object); stringghi đè phương thức này và thực hiện so sánh thứ tự trên nội dung chuỗi. Xem msdn.microsoft.com/en-us/library/fkfd9eh8(v=vs.110).aspxreferencesource.microsoft.com/#mscorlib/system/string.cs,507 .
phoog

6
Giải thích của @ phoog là chính xác. Cần lưu ý rằng khi phía bên trái ==có kiểu thời gian biên dịch objectvà phía bên phải có kiểu thời gian biên dịch string, thì trình biên dịch C # phải chọn quá tải (có vấn đề, trong trường hợp này) operator ==(object, object); nhưng nó sẽ đưa ra một cảnh báo thời gian biên dịch rằng nó có thể là ngoài ý muốn. Vì vậy, đọc các cảnh báo thời gian biên dịch! Để khắc phục sự cố và vẫn sử dụng ==, hãy đặt phía bên trái sang string. Nếu tôi nhớ chính xác, văn bản cảnh báo gợi ý rằng.
Jeppe Stig Nielsen

1
@JeppeStigNielsen +1 để được tư vấn đọc cảnh báo về trình biên dịch. Thậm chí tốt hơn: bật tùy chọn cảnh báo là lỗi để buộc mọi người phải chú ý đến chúng.
phoog

Câu trả lời:


429

Khi ==được sử dụng trên một biểu thức của loại object, nó sẽ giải quyết System.Object.ReferenceEquals.

Equalschỉ là một virtualphương thức và hành xử như vậy, vì vậy phiên bản ghi đè sẽ được sử dụng (trong đó, đối với stringkiểu so sánh nội dung).


57
Trừ khi nhà điều hành được triển khai cụ thể trong lớp
Dominic Cronin

23
@DominicCronin Điều này không đúng. Ngay cả khi == được triển khai trong lớp, nó sẽ bị bỏ qua vì kiểu bên trái của phép so sánh là đối tượng. Có vẻ như quá tải toán tử được xác định tại thời gian biên dịch và tại thời gian biên dịch, tất cả những gì nó biết là phía bên trái là một đối tượng.
MikeKulls

4
@DominicCronin Tôi tin rằng tuyên bố đầu tiên của bạn là chính xác trong đó == sẽ giải quyết đối tượng nhưng tuyên bố thứ hai của bạn rằng quá tải toán tử giải quyết theo cách tương tự thì không. Chúng khá khác nhau, đó là lý do tại sao .Equals sẽ phân giải thành chuỗi trong khi == sẽ phân giải thành đối tượng.
MikeKulls

8
Để rõ ràng, objectgõ (chú ý phông chữ đơn cách) về mặt kỹ thuật có nghĩa là "một biểu thức của loại System.Object". Nó không có gì để làm với kiểu thời gian chạy của thể hiện được gọi bằng biểu thức. Tôi nghĩ rằng tuyên bố "toán tử do người dùng định nghĩa được coi là virtualphương thức" là rất sai lệch. Chúng được xử lý như các phương thức quá tải và chỉ phụ thuộc vào kiểu thời gian biên dịch của toán hạng. Trong thực tế, sau khi tập hợp các toán tử do người dùng định nghĩa được tính toán, phần còn lại của quy trình liên kết sẽ chính xác là thuật toán giải quyết quá tải phương thức
Mehrdad Afshari

4
@DominicCronin Phần gây hiểu lầm là virtualđộ phân giải phương thức phụ thuộc vào kiểu thời gian chạy thực tế của một thể hiện, trong khi đó hoàn toàn bị bỏ qua trong độ phân giải quá tải của toán tử và đó thực sự là toàn bộ câu trả lời của tôi.
Mehrdad Afshari

314

Khi so sánh một tham chiếu đối tượng với một chuỗi (ngay cả khi tham chiếu đối tượng tham chiếu đến một chuỗi), hành vi đặc biệt của ==toán tử dành riêng cho lớp chuỗi bị bỏ qua.

Thông thường (khi không xử lý chuỗi, nghĩa là), Equalsso sánh các giá trị , trong khi ==so sánh các tham chiếu đối tượng . Nếu hai đối tượng bạn đang so sánh đang đề cập đến cùng một thể hiện chính xác của một đối tượng, thì cả hai sẽ trả về đúng, nhưng nếu một đối tượng có cùng nội dung và đến từ một nguồn khác nhau (là một thể hiện riêng biệt có cùng dữ liệu), thì chỉ có Bằng Trả lại đúng. Tuy nhiên, như đã lưu ý trong các nhận xét, chuỗi là trường hợp đặc biệt vì nó ghi đè ==toán tử để khi xử lý hoàn toàn các tham chiếu chuỗi (và không tham chiếu đối tượng), chỉ các giá trị được so sánh ngay cả khi chúng là các trường hợp riêng biệt. Đoạn mã sau minh họa sự khác biệt tinh tế trong hành vi:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

Đầu ra là:

True True True
False True True
False False True

8
Tại chỗ trên. Toán tử '==' so sánh các tham chiếu đối tượng (so sánh nông) trong khi .Equals () so sánh nội dung đối tượng (so sánh sâu). Như @mehrdad đã nói, .Equals () được ghi đè để cung cấp so sánh nội dung sâu sắc đó.
Andrew

1
Tôi sẽ để lại bài viết ở đây vì tôi nghĩ thật có giá trị để nhấn mạnh những gì không xảy ra vì bạn phải hết sức chú ý để nhận ra nó. (Và tôi nghĩ rằng mã để chứng minh những hiểu biết chính xác và không chính xác cũng đáng giá.) Tôi hy vọng xếp hạng sẽ không xuống dưới 0.
BlueMonkMN

5
Chắc chắn String thực hiện một toán tử == tùy chỉnh. Nếu không thì sử dụng == sẽ không so sánh nội dung. Vì vậy, String là một ví dụ tồi để sử dụng ở đây, vì nó không giúp chúng ta hiểu trường hợp chung khi không có toán tử tùy chỉnh nào được xác định.
Đaminh Cronin

6
+1 cho ví dụ mã sử thi, điều đó khiến tôi hiểu điều này. Hiển thị trường hợp chung của loại tĩnh (loại Bên tay trái) là đối tượng và trường hợp cụ thể của loại tĩnh (loại RHS) là chuỗi. Và chạm tốt vào chuỗi thực tập.
barlop

2
@badsamaritan Vì thực tập theo chuỗi
Alexander Derck

46

==.Equalscả hai đều phụ thuộc vào hành vi được xác định trong loại thực tế và loại thực tế tại trang web cuộc gọi. Cả hai chỉ là các phương thức / toán tử có thể được ghi đè trên bất kỳ loại nào và đưa ra bất kỳ hành vi nào mà tác giả mong muốn. Theo kinh nghiệm của tôi, tôi thấy mọi người thường thực hiện .Equalstrên một đối tượng nhưng bỏ qua việc thực hiện toán tử ==. Điều này có nghĩa là .Equalssẽ thực sự đo lường sự bằng nhau của các giá trị trong khi ==sẽ đo xem chúng có cùng tham chiếu hay không.

Khi tôi làm việc với một loại mới có định nghĩa là thông lượng hoặc viết các thuật toán chung, tôi thấy cách thực hành tốt nhất là như sau

  • Nếu tôi muốn so sánh các tham chiếu trong C #, tôi sử dụng Object.ReferenceEqualstrực tiếp (không cần trong trường hợp chung)
  • Nếu tôi muốn so sánh các giá trị tôi sử dụng EqualityComparer<T>.Default

Trong một số trường hợp khi tôi cảm thấy việc sử dụng ==không rõ ràng, tôi sẽ sử dụng rõ ràng Object.Referencebằng mã trong mã để loại bỏ sự mơ hồ.

Eric Lippert gần đây đã làm một bài đăng trên blog về chủ đề tại sao có 2 phương pháp bình đẳng trong CLR. Nó đáng để đọc


Chà, Jared, bạn vi phạm trực tiếp nổi tiếng của Jeff. Mã tốt nhất là không có mã nào ở đây. Điều này có thực sự hợp lý? Mặt khác, tôi có thể thấy điều này bắt nguồn từ đâu và tại sao nó có thể được mong muốn để làm cho ngữ nghĩa rõ ràng. Trong trường hợp này, tôi rất thích cách xử lý đối tượng bình đẳng của VB. Nó ngắn không mơ hồ.
Konrad Rudolph

@Konrad, tôi thực sự nên nói "khi tôi không quen thuộc với một loại, tôi thấy cách thực hành tốt nhất là như sau". Có VB có ngữ nghĩa tốt hơn nhiều ở đây vì nó thực sự tách biệt giá trị và bình đẳng tham chiếu. C # trộn cả hai lại với nhau và đôi khi nó gây ra lỗi mơ hồ.
JaredPar

10
Điều này không hoàn toàn đúng. == không thể bị ghi đè, đó là một phương thức tĩnh. Nó chỉ có thể bị quá tải, đó là một sự khác biệt quan trọng. Vì vậy, mã được thực thi cho toán tử == được liên kết tại thời gian biên dịch, trong khi Equals là ảo và được tìm thấy tại thời điểm thực thi.
Stefan Steinegger

20

== Toán tử

  1. Nếu toán hạng là Loại giá trịgiá trị của chúng bằng nhau, nó sẽ trả về giá trị true khác.
  2. Nếu toán hạng là Kiểu tham chiếu ngoại trừ chuỗi và cả hai đều tham chiếu đến cùng một thể hiện (cùng một đối tượng), thì nó trả về true khác false.
  3. Nếu toán hạng là kiểu chuỗigiá trị của chúng bằng nhau, nó trả về true khác false.

.Equals

  1. Nếu toán hạng là Kiểu tham chiếu , nó thực hiện Bình đẳng tham chiếu , nếu cả hai đều tham chiếu đến cùng một thể hiện (cùng một đối tượng), thì nó trả về true khác false.
  2. Nếu các toán tử là các loại giá trị thì không giống như toán tử ==, nó sẽ kiểm tra loại của chúng trước và nếu các kiểu của chúng giống nhau thì nó thực hiện == toán tử khác, nó trả về false.

2
Điều này LAF không đúng. Các ==nhà điều hành có thể bị quá tải cho bất kỳ loại, không chỉ là chuỗi. Việc mô tả một trường hợp ngoại lệ đặc biệt chỉ dành cho các chuỗi hiểu sai về ngữ nghĩa của toán tử. Sẽ chính xác hơn, mặc dù có lẽ không hữu ích lắm, khi nói "nếu toán hạng là loại tham chiếu thì nó trả về đúng nếu toán hạng tham chiếu đến cùng một đối tượng, trừ khi có quá tải áp dụng, trong trường hợp đó, việc thực hiện quá tải đó xác định kết quả ". Điều tương tự cũng đúng Equalsvới sự phức tạp thêm vào đó là một phương thức ảo, vì vậy hành vi của nó có thể bị ghi đè cũng như quá tải.
phoog

19

Thứ nhất, có một sự khác biệt. Đối với số

> 2 == 2.0
True

> 2.Equals(2.0)
False

Và cho chuỗi

> string x = null;
> x == null
True

> x.Equals(null)
NullReferenceException

Trong cả hai trường hợp, ==hành xử hữu ích hơn.Equals


2
Tôi không chắc chắn tôi coi sự ép buộc của các loại tích phân đối với các loại dấu phẩy động với ==toán tử là một điều tốt. Ví dụ: 16777216.0f bằng (int) 16777217, (double) 16777217.0, cả hai hay không? So sánh giữa các loại tích phân là tốt, nhưng so sánh dấu phẩy động chỉ nên được thực hiện IMHO với các giá trị được truyền rõ ràng cho các loại khớp. Việc so sánh a floatvới một thứ gì đó không phải là a float, hay a doublevới thứ gì khác ngoài a double, đánh vào tôi như một mùi mã chính không nên biên dịch nếu không có chẩn đoán.
supercat

1
@supercat Tôi đồng ý với điều đó, nó thật khó chịu mà x == ykhông bao hàm x/3 == y/3(thử x = 5y = 5.0).
Đại tá Panic

Tôi coi việc sử dụng /phân chia số nguyên là một khiếm khuyết trong thiết kế của C # và Java. Mặc dù vậy, Pascal divvà thậm chí VB.NET là ` are much better. The problems with == `tệ hơn: x==yy==zkhông ngụ ý điều đó x==z(hãy xem xét ba số trong nhận xét trước của tôi). Đối với mối quan hệ mà bạn đề xuất, ngay cả khi xycả hai floathoặc cả hai double, x.equals((Object)y)không ngụ ý rằng 1.0f/x == 1.0f / y` (nếu tôi có máy khoan của mình, nó sẽ đảm bảo rằng, ngay cả khi ==không phân biệt dương và bằng 0, Equalsnên).
supercat

Điều đó là bình thường, bởi vì tham số đầu tiên của Equals () là một chuỗi!
Whiplash

17

Theo tôi hiểu thì câu trả lời rất đơn giản:

  1. == so sánh các tham chiếu đối tượng.
  2. .Equals so sánh nội dung đối tượng.
  3. String kiểu dữ liệu luôn luôn hoạt động như so sánh nội dung.

Tôi hy vọng tôi đúng và nó đã trả lời câu hỏi của bạn.


15

Tôi sẽ thêm rằng nếu bạn truyền đối tượng của bạn thành một chuỗi thì nó sẽ hoạt động chính xác. Đây là lý do tại sao trình biên dịch sẽ cung cấp cho bạn một cảnh báo:

Có thể so sánh tham khảo ngoài ý muốn; để có được sự so sánh giá trị, hãy đặt phía bên trái để nhập 'chuỗi'


1
Chính xác. @DominicCronin: Luôn tuân thủ các cảnh báo về thời gian biên dịch. Nếu bạn có object expr = XXX; if (expr == "Energy") { ... }, thì vì phía bên trái là kiểu thời gian objectbiên dịch, trình biên dịch phải sử dụng quá tải operator ==(object, object). Nó kiểm tra sự bình đẳng tham chiếu. Cho dù điều đó sẽ cho truehoặc falsecó thể khó dự đoán vì thực tập chuỗi . Nếu bạn biết phía bên trái là một trong hai nullloại string, hãy đặt bên trái sang stringtrước khi sử dụng ==.
Jeppe Stig Nielsen

để đặt một phần của cách đó khác. == (trong việc xác định xem nó sử dụng đẳng thức tham chiếu hay đẳng thức giá trị) phụ thuộc vào loại thời gian biên dịch / loại tĩnh / loại bên trái. (đó là loại được giải quyết trong phân tích thời gian biên dịch). Thay vì kiểu thời gian chạy / kiểu động / kiểu RHS. Mã của BlueMonkMN cho thấy, mặc dù không phải bằng cách truyền.
barlop

5

Do phiên bản tĩnh của .Equalphương thức không được đề cập cho đến nay, tôi muốn thêm phần này vào đây để tóm tắt và so sánh 3 biến thể.

MyString.Equals("Somestring"))          //Method 1
MyString == "Somestring"                //Method 2
String.Equals("Somestring", MyString);  //Method 3 (static String.Equals method) - better

nơi MyStringlà một biến xuất phát từ một nơi khác trong mã.

Thông tin cơ bản và để mùa hè:

Trong Java sử dụng ==để so sánh các chuỗi không nên được sử dụng. Tôi đề cập đến điều này trong trường hợp bạn cần sử dụng cả hai ngôn ngữ và cũng để cho bạn biết rằng việc sử dụng ==cũng có thể được thay thế bằng một thứ tốt hơn trong C #.

Trong C # không có sự khác biệt thực tế nào để so sánh các chuỗi sử dụng Phương thức 1 hoặc Phương pháp 2 miễn là cả hai đều thuộc loại chuỗi. Tuy nhiên, nếu một là null, một thuộc loại khác (như số nguyên) hoặc một đại diện cho một đối tượng có tham chiếu khác, thì, như câu hỏi ban đầu cho thấy, bạn có thể trải nghiệm rằng so sánh nội dung cho đẳng thức có thể không trả về bạn mong đợi.

Đề xuất giải pháp:

Vì việc sử dụng ==không hoàn toàn giống như sử dụng .Equalskhi so sánh mọi thứ, nên bạn có thể sử dụng phương thức String.Equals tĩnh thay thế. Bằng cách này, nếu hai bên không cùng loại, bạn vẫn sẽ so sánh nội dung và nếu một bên là null, bạn sẽ tránh được ngoại lệ.

   bool areEqual = String.Equals("Somestring", MyString);  

Nó là một ít hơn để viết, nhưng theo tôi, an toàn hơn để sử dụng.

Dưới đây là một số thông tin được sao chép từ Microsoft:

public static bool Equals (string a, string b);

Thông số

a Chuỗi

Chuỗi đầu tiên để so sánh, hoặc null.

b Chuỗi

Chuỗi thứ hai để so sánh, hoặc null.

Trả về Boolean

truenếu giá trị của agiống như giá trị của b; nếu không false. Nếu cả hai abnull, phương thức trả về true.


5

Cũng giống như một bổ sung cho các câu trả lời đã tốt: Hành vi này KHÔNG giới hạn ở Chuỗi hoặc so sánh các kiểu số khác nhau. Ngay cả khi cả hai phần tử thuộc loại đối tượng cùng loại. "==" sẽ không hoạt động.

Ảnh chụp màn hình sau đây cho thấy kết quả so sánh hai đối tượng {int} - giá trị

Ví dụ từ VS2017


2

Tôi hơi bối rối ở đây. Nếu loại Nội dung thời gian chạy là loại chuỗi, thì cả == và Equals sẽ trả về true. Tuy nhiên, vì điều này dường như không phải là trường hợp, nên loại Nội dung thời gian chạy không phải là chuỗi và gọi Equals trên đó là một đẳng thức tham chiếu và điều này giải thích tại sao Equals ("Tấn công năng lượng") thất bại. Tuy nhiên, trong trường hợp thứ hai, quyết định về việc quá tải == toán tử tĩnh sẽ được gọi được đưa ra tại thời điểm biên dịch và quyết định này dường như là == (chuỗi, chuỗi). điều này gợi ý cho tôi rằng Nội dung cung cấp một chuyển đổi ngầm định thành chuỗi.


2
Bạn có nó trở lại phía trước. Để bắt đầu Bằng ("Tấn công năng lượng") không thất bại, == là giá trị trả về sai. == thất bại vì nó đang sử dụng == từ đối tượng, không phải chuỗi.
MikeKulls

Theo mặc định, toán tử == kiểm tra sự bằng nhau của tham chiếu bằng cách xác định xem hai tham chiếu có chỉ ra cùng một đối tượng hay không. Do đó, các loại tham chiếu không phải triển khai toán tử == để có được chức năng này. Khi một loại là bất biến, nghĩa là, dữ liệu chứa trong thể hiện không thể thay đổi, toán tử nạp chồng == để so sánh đẳng thức giá trị thay vì đẳng thức tham chiếu có thể hữu ích vì, như các đối tượng bất biến, chúng có thể được coi là giống nhau miễn là vì chúng có cùng giá trị. Nó không phải là một ý tưởng tốt để ghi đè toán tử == trong các loại không thay đổi.
Wajeed-MSFT

2

Có một khía cạnh khác cho câu trả lời trước đó của @BlueMonkMN. Thứ nguyên bổ sung là câu trả lời cho câu hỏi tiêu đề của @ Drahcir như đã nêu cũng phụ thuộc vào cách chúng tôi đạt được stringgiá trị. Để minh họa:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));

Console.WriteLine("\n  Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

Console.WriteLine("\n  Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));

Đầu ra là:

True True True

  Case1 - A method changes the value:
False True True
False False True

  Case2 - Having only literals allows to arrive at a literal:
True True True
True True True

2

Thêm một điểm nữa cho câu trả lời.

.EqualsTo() phương pháp cung cấp cho bạn điều khoản để so sánh với văn hóa và trường hợp nhạy cảm.


0

==thông báo trong C # được sử dụng cho hai toán tử kiểm tra đẳng thức khác nhau. Khi trình biên dịch gặp mã thông báo đó, nó sẽ kiểm tra xem một trong hai loại được so sánh có thực hiện quá tải toán tử đẳng thức cho các loại kết hợp cụ thể được so sánh (*) hay không, hoặc kết hợp các loại mà cả hai loại có thể được chuyển đổi. Nếu trình biên dịch tìm thấy quá tải như vậy, nó sẽ sử dụng nó. Mặt khác, nếu hai loại đều là loại tham chiếu và chúng không phải là các lớp không liên quan (có thể là giao diện hoặc chúng có thể là các lớp liên quan), trình biên dịch sẽ coi ==là toán tử so sánh tham chiếu. Nếu không áp dụng điều kiện, việc biên dịch sẽ thất bại.

Lưu ý rằng một số ngôn ngữ khác sử dụng mã thông báo riêng cho hai toán tử kiểm tra đẳng thức. Ví dụ, trong VB.NET, =mã thông báo chỉ được sử dụng trong các biểu thức cho toán tử kiểm tra đẳng thức quá tải và Isđược sử dụng làm toán tử kiểm tra tham chiếu hoặc kiểm tra null. Việc sử dụng =trên một loại không ghi đè toán tử kiểm tra đẳng thức sẽ không thành công, vì sẽ cố gắng sử dụng Ischo bất kỳ mục đích nào khác ngoài kiểm tra tính bằng hoặc tham chiếu tham chiếu.

(*) Các loại nói chung chỉ quá tải bình đẳng để so sánh với chính chúng, nhưng có thể hữu ích cho các loại để quá tải toán tử đẳng thức để so sánh với các loại cụ thể khác; ví dụ, intcó thể có (và IMHO nên có nhưng không) đã xác định một toán tử đẳng thức để so sánh với float, do đó 16777217 sẽ không tự báo cáo bằng 16777216f. Vì vậy, vì không có toán tử nào được xác định, C # sẽ quảng bá intđến float, làm tròn nó thành 16777216f trước khi toán tử kiểm tra đẳng thức nhìn thấy nó; toán tử đó sau đó thấy hai số dấu phẩy động bằng nhau và báo cáo chúng là bằng nhau, không biết về việc làm tròn đã diễn ra.


Thay vì có một so sánh int-to-float trả về false, tôi thích cách tiếp cận mà F # sử dụng, đó là không cho phép so sánh như vậy. Sau đó, lập trình viên có thể quyết định xem và làm thế nào để xử lý thực tế là các giá trị có loại khác nhau. Bởi vì đôi khi, sau khi tất cả, chúng tôi làm muốn điều trị 3như là tương đương 3.0f. Nếu chúng tôi yêu cầu lập trình viên nói những gì được dự định trong mọi trường hợp, thì không có nguy cơ hành vi mặc định dẫn đến kết quả ngoài ý muốn, vì không có hành vi mặc định.
phoog

@phoog: Cảm nhận cá nhân của tôi là các ngôn ngữ nên có phương tiện kiểm tra đẳng thức "bình thường" của chúng thực hiện mối quan hệ tương đương và cấm tất cả các kết hợp toán hạng mà nó sẽ không sử dụng. Tôi không thấy một lợi thế lớn khi có sự kiểm tra ngôn ngữ bình đẳng giữa số nguyên và số float bằng cách xác nhận rằng một số float đại diện chính xác cho toàn bộ số khớp với int, so với việc cấm so sánh như vậy, nhưng sẽ xem xét cách tiếp cận vượt trội hơn so với việc thực hiện ngôn ngữ một chuyển đổi mất mát trước khi so sánh.
supercat

0

Những câu trả lời và ví dụ thực sự tuyệt vời!

Tôi chỉ muốn thêm sự khác biệt cơ bản giữa hai,

Các toán tử như ==không đa hình, trong khi Equals

Với ý tưởng đó, nếu bạn tìm ra bất kỳ ví dụ nào (bằng cách nhìn vào loại tham chiếu tay trái và tay phải và kiểm tra / biết nếu loại thực sự có == toán tử bị quá tải và Bằng cách bị chồng chéo), bạn chắc chắn sẽ có câu trả lời đúng .


-1

Khi chúng ta tạo bất kỳ đối tượng nào, có hai phần đối tượng, một phần là nội dung và phần còn lại là tham chiếu đến nội dung đó. ==so sánh cả nội dung và tài liệu tham khảo; equals()chỉ so sánh nội dung

http://www.codeproject.com/Articles/584128/What-is-the-difference-b between-Equal resultals-and-Eq


1
Đây không phải là sự thật. Nếu ablà cả hai tham chiếu chuỗi, thì kết quả của a == bkhông phụ thuộc vào việc các tham chiếu có trỏ đến cùng một đối tượng hay không.
phoog

-2

==

Toán tử == có thể được sử dụng để so sánh hai biến thuộc bất kỳ loại nào và nó chỉ đơn giản là so sánh các bit .

int a = 3;
byte b = 3;
if (a == b) { // true }

Lưu ý: có nhiều số 0 ở bên trái của int nhưng chúng tôi không quan tâm đến điều đó ở đây.

int a (00000011) == byte b (00000011)

Ghi nhớ == toán tử chỉ quan tâm đến mô hình của các bit trong biến.

Sử dụng == Nếu hai tham chiếu (nguyên thủy) tham chiếu đến cùng một đối tượng trên heap.

Các quy tắc là như nhau cho dù biến là một tham chiếu hoặc nguyên thủy.

Foo a = new Foo();
Foo b = new Foo();
Foo c = a;

if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }

a == c là đúng a == b là sai

mẫu bit giống nhau cho a và c, vì vậy chúng bằng nhau khi sử dụng ==.

Công bằng():

Sử dụng phương thức equals () để xem hai đối tượng khác nhau có bằng nhau không .

Chẳng hạn như hai đối tượng String khác nhau đại diện cho các nhân vật trong "Jane"


2
Điều này là không chính xác. Hãy xem xét những điều sau đây : object a = 3; object b = 3; Console.WriteLine(a == b);. Đầu ra là sai, mặc dù các mẫu bit của các giá trị là như nhau. Các loại toán hạng cũng quan trọng. Lý do chúng tôi "không quan tâm" về số lượng số 0 khác nhau trong ví dụ của bạn là vào thời điểm chúng tôi gọi toán tử bằng, số lượng số không thực sự giống nhau , vì chuyển đổi ngầm định.
phoog

-2

Sự khác biệt duy nhất giữa Equal và == là so sánh kiểu đối tượng. trong các trường hợp khác, chẳng hạn như các loại tham chiếu và các loại giá trị, chúng gần như giống nhau (cả hai đều là đẳng thức bit-khôn ngoan hoặc cả hai đều là đẳng thức tham chiếu).

object: Equals: bit-khôn đẳng ==: đẳng thức tham chiếu

chuỗi: (bằng và == là giống nhau cho chuỗi, nhưng nếu một chuỗi thay đổi thành đối tượng, thì kết quả so sánh sẽ khác nhau) Bằng: bình đẳng bit-khôn ==: đẳng thức bit-khôn

Xem ở đây để giải thích thêm.


Object.Equals không nhất thiết phải nhìn vào đẳng thức bitwise. Đây là một phương thức ảo và ghi đè có thể làm bất cứ điều gì nó muốn.
phoog

vâng, bạn đúng, bạn có thể làm bất cứ điều gì bạn muốn ghi đè lên nó. nhưng chủ đề chúng ta đang nói là việc thực hiện mặc định. việc triển khai mặc định của Object.Equals là sự bình đẳng bit-khôn ngoan.
Will Yu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.