2010-06-09 13 views
16

khi tôi cố gắng quá tải toán tử == và! = Trong C# và ghi đè như được đề xuất, tôi tìm thấy Tôi không có cách nào để phân biệt một đối tượng bình thường và null. Ví dụ, tôi đã định nghĩa một lớp phức tạp.overload == (và! =, Tất nhiên) nhà điều hành, tôi có thể bỏ qua == để xác định xem đối tượng có rỗng không

public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    return lhs.Equals(rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !lhs.Equals(rhs); 
} 

public override bool Equals(object obj) 
{ 
    if (obj is Complex) 
    { 
     return (((Complex)obj).Real == this.Real && 
        ((Complex)obj).Imaginary == this.Imaginary); 
    } 
    else 
    { 
     return false; 
    } 
} 

Nhưng khi tôi muốn sử dụng

if (temp == null) 

Khi tạm thời thực sự là null, một số ngoại lệ xảy ra. Và tôi không thể sử dụng == để xác định xem các lhs là null, mà sẽ gây ra vòng lặp vô hạn.

Tôi nên làm gì trong tình huống này.

Một cách tôi có thể nghĩ là đối với chúng tôi một số thứ như Class.Equal (đối tượng, đối tượng) (nếu nó tồn tại) để bỏ qua == khi tôi thực hiện kiểm tra.

Cách bình thường để giải quyết vấn đề là gì?

Cảm ơn bạn.

+0

bản sao có thể có của [Làm cách nào để kiểm tra các giá trị rỗng trong toán tử '==' quá tải mà không có đệ quy vô hạn?] (Http://stackoverflow.com/questions/73713/how-do-i-check-for-nulls -in-an-operator-overload-without-infinite-recursion) – Sam

Trả lời

10

Bạn nên xem xét sử dụng tĩnh Bằng phương pháp trong phiên bản nạp chồng toán tử (mà sẽ gọi dụ Bằng phương pháp):

public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    return Equals(lhs, rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !Equals(lhs, rhs); 
} 

Lưu ý: Bạn cũng có thể kiểm tra null trong phương thức Equals.

Bạn cũng có thể đọc số Object.Equals Topic on MSDN, đây là nguồn mẫu tuyệt vời.

+0

Cảm ơn, nó hoạt động, nhưng tôi không chắc tại sao. Và tại sao Object có thể bị bỏ qua trong Object.Equals()? Và tôi đã không tìm thấy lý do tại sao điều này có thể ngăn chặn các vấn đề null trong MSDN. (Nó có kiểm tra null trước không?) – LLS

+1

Bạn không cần tiền tố lớp Object vì Complex kế thừa từ Object; Phức tạp xem các phương pháp tĩnh của Object. Tôi không biết nội bộ của phương thức Equals tĩnh, nhưng nó có khả năng kiểm tra null trước khi gọi phương thức Equals instance. –

+1

Nếu lhs không phải là null Equals gọi phương thức instance = bằng lhs. Nếu lhs là null Bằng so sánh các tham chiếu của lhs và rhs. –

14

Bạn có thể sử dụng sau đây ở đầu Equals bạn ghi đè lên:

if (Object.ReferenceEquals(obj, null)) 
    return false; 

Trường hợp ngoại lệ bạn đang nhận được có lẽ là một StackOverflowException vì toán tử == bạn sẽ gây ra đệ quy vô hạn.

EDIT:

Nếu Complex là một struct bạn không nên có bất kỳ vấn đề với NullReferenceExceptions. ! Nếu Complex là một lớp học mà bạn có thể thay đổi thực hiện của bạn của == và = điều hành quá tải để tránh sự ngoại lệ (Laurent Etiemble đã chỉ ra điều này trong câu trả lời của mình):

public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    return Equals(lhs, rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !Equals(lhs, rhs); 
} 
+0

Trên thực tế nó là tham chiếu Object không được đặt thành một thể hiện của một đối tượng. Nó sẽ hoạt động, cảm ơn. :) – LLS

+0

Ngoại lệ vẫn tồn tại, vì null.Equals() được cố gắng gọi. – LLS

+0

Tôi muốn xem xét việc làm phức tạp một cấu trúc thay vì một lớp. –

0

Có một cách tiếp cận tốt hơn sau đó sử dụng các nhà khai thác iscast:

Complex c = obj as Complex; 
return (c != null) && (c.Real == this.Real) && (c.Imaginary == this.Imaginary); 

Dưới đây là một thử nghiệm nhanh về Equals hành ghi đè và so sánh với null:

class Complex 
{ 
    public override bool Equals(object obj) 
    { 
     if (obj is Complex) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

Debugging không bước vào cơ quan của nhà điều hành:

var b = (new Complex() == new Complex()); 
+0

Cảm ơn, nhưng có vẻ như c! = Null sẽ gây ra vòng lặp vô hạn. – LLS

+0

@LLS: Thật sao? Hấp dẫn. Không chắc chắn rằng so sánh với 'null' sẽ sử dụng toán tử so sánh' đối tượng'. Nhưng có thể .. – abatishchev

+0

@LLS: Xem bài đăng cập nhật của tôi – abatishchev

2
public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    if (Object.ReferenceEquals(lhs, null)) 
    { 
     return Object.ReferenceEquals(rhs, null); 
    } 

    return lhs.Equals(rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !(lhs == rhs); 
} 

kiểm tra đơn vị nghèo của con người

Action<Complex, Complex> tester = (left, right) => 
{ 
    Console.WriteLine(left == right); 
    Console.WriteLine(left != right); 
    Console.WriteLine(left == null); 
    Console.WriteLine(left != null); 
    Console.WriteLine("---"); 
}; 

tester(new Complex(), new Complex()); 
tester(null, new Complex()); 
tester(null, null); 
tester(new Complex(), null); 
+0

Cảm ơn rất nhiều. Thật dễ hiểu. – LLS

0

Tôi nghĩ bạn shoud kiểm tra null trong việc thực hiện toán tử ==. Nếu không, khi lhs là null, bạn gọi hàm Complex (null) .Equals (Tôi không biết cho C#, nhưng trong Java thì đây sẽ là một ngoại lệ Nullpointer)

Để kiểm tra null, tôi đề nghị một cái gì đó như:

if (null == lhs && null == rhs) return true 
else if (null == lhs) return false 
else return lhs.Equals(rhs); 

Vì vậy, đối tượng sẽ được gọi cho tất cả các so sánh == ở trên.

+0

Bạn nhận được một cuộc gọi đệ quy đến toán tử ==. –

+0

Ok, thú vị. Chỉ tò mò thôi, làm thế nào mà toán tử == (phức tạp, phức tạp) được gọi, khi tôi kiểm tra null == lhs? Trình biên dịch quyết định rằng "null" là kiểu phức tạp như thế nào? – nang

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