2010-09-16 14 views
5

Tôi bị ảnh hưởng bởi "sự bất đối xứng" lạ trong C# mà tôi không thực sự hiểu. Xem mã sau:Object.Equals là ảo, nhưng Object.operator == không sử dụng nó trong C#?

using System; 
using System.Diagnostics; 
namespace EqualsExperiment 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      object apple = "apple"; 
      object orange = string.Format("{0}{1}", "ap", "ple"); 
      Console.WriteLine("1"); 
      Debug.Assert(apple.Equals(orange)); 
      Console.WriteLine("2"); 
      Debug.Assert(apple == orange); 
      Console.WriteLine("3"); 
     } 
    } 
} 

Điều này có thể hiển nhiên đối với tất cả các bạn .NET gurus, nhưng khẳng định thứ 2 không thành công.

Trong Java tôi đã học được rằng == là một từ đồng nghĩa cho một cái gì đó gọi là Object.ReferenceEquals ở đây. Trong C#, tôi nghĩ rằng Object.operator == sử dụng Object.Equals, là ảo, vì vậy nó được overriden trong lớp System.String.

Ai đó có thể giải thích, tại sao xác nhận thứ 2 thất bại trong C#? Giả định nào của tôi là xấu?

+0

Tôi đã tìm thấy [answer] (http://stackoverflow.com/questions/1766492/c-overloading-operator-versus-equals/1849288#1849288) cho câu hỏi của mình cũng trong một chuỗi khác. Có vẻ như 'object.operator ==' sử dụng 'object.ReferenceEquals', nhưng' string.operator == 'sử dụng' object.Equals'. Điều này phản trực giác với tôi, bởi vì 'object.Equals' là ảo, vì vậy nó có thể được sử dụng trong' object.operator == '. – wigy

Trả lời

7

Toán tử == không phải là một từ đồng nghĩa, đó là toán tử được xác định cho các loại khác nhau.

Nhà điều hành == được định nghĩa cho các chuỗi, và sau đó nó không thực sự sử dụng Equals phương pháp:

public static bool operator ==(string a, string b) { 
    return Equals(a, b); 
} 

Tuy nhiên, trong mã của bạn, bạn không sử dụng các nhà điều hành trên dây, bạn đang sử dụng nó trên các đối tượng, vì vậy những gì bạn nhận được là toán tử == được xác định cho các đối tượng, sử dụng ReferenceEquals để so sánh.

Quá tải của toán tử được sử dụng được quyết định trong thời gian biên dịch, vì vậy đó là loại biến quyết định quá tải, không phải là loại đối tượng thực tế mà các biến trỏ tới.

+0

Hmmm. Vì vậy, bạn nói rằng Object.operator == được định nghĩa với ReferenceEquals, trong khi String.operator == được định nghĩa bằng Equals. Không đẹp và trực quan sao? – wigy

+1

@wigy: Hầu hết thời gian nó hoạt động rất tốt, nhưng có những tình huống tất nhiên như ví dụ của bạn, nơi bạn có thể mong đợi sự so sánh được xác định khi chạy. Nó chắc chắn trực quan hơn ví dụ trong C++ và Java, nơi bạn không thể sử dụng toán tử == một cách đáng tin cậy. Trong VB toán tử = xác định so sánh trong thời gian chạy, điều này phù hợp hơn với cách VB hoạt động, nhưng điều đó đưa ra một số tình huống khác khiến nó có thể làm bạn ngạc nhiên. Trong C# có thể xác định từ mã chính xác so sánh nào sẽ được sử dụng, điều này phù hợp hơn với cách C# hoạt động nói chung. – Guffa

+0

Cảm ơn Guffa. Tôi biết nó là tốt hơn so với C, Java hoặc VB. Các toán tử C++ có thể là ảo, vì vậy bạn có các vấn đề khác nhau ở đó.Đó là lý do tại sao hầu hết các tiêu chuẩn mã hóa C++ sử dụng điều kiện Yoda như 'if (5 == something) {...}' Từ câu trả lời của bạn, tôi hiểu rằng các nhà thiết kế khuôn khổ nghĩ ReferenceEquals trực quan hơn đối với một số lập trình viên, nhưng chuỗi cố định .operator == mặt khác. – wigy

6

Toán tử được định nghĩa là phương thức tĩnh, vì vậy chúng không thể tham gia vào đa hình. Vì vậy, xác nhận thứ hai của bạn sử dụng định nghĩa của == cho object (vì các biến của bạn được khai báo là object), chỉ kiểm tra tính bình đẳng tham chiếu. Nếu các biến được khai báo là string, quá tải == cho string sẽ được sử dụng và xác nhận thứ hai sẽ thành công.

+2

Cũng đáng chú ý, cho đầy đủ, rằng 'object.Equals tĩnh (táo, cam)' sẽ trả về 'true' trong trường hợp này. 'object.Equals' đầu tiên sử dụng' == 'để kiểm tra sự bình đẳng ref, và nếu thất bại nó sẽ sử dụng quá tải' apple.Equals (orange) '(giả sử rằng' apple' và 'orange' không phải là' null'). – LukeH

+0

Tôi hiểu rằng tôi sử dụng 'static bool Object.operator == (Object, Object)'. Nhưng tôi vẫn không hiểu, tại sao không gọi là 'Object.Equals (Object) '. Vì đó là ảo, 'String.Equals (Object)' chính xác sẽ được gọi vào cuối. – wigy

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