2008-09-30 8 views
17

Tôi cần phải thực hiện một comparaison giữa một đối tượng và NULL. Khi đối tượng không phải là NULL, tôi điền nó với một số dữ liệu.Đối tượng C# không phải là null nhưng (myObject! = Null) vẫn trả về false

Đây là mã:

if (region != null) 
{ 
    .... 
} 

này đang làm việc nhưng khi vòng lặp và vòng lặp đôi khi đối tượng khu vực là KHÔNG null (tôi có thể xem dữ liệu bên trong nó trong chế độ gỡ lỗi). Trong từng bước khi gỡ lỗi, nó không đi vào bên trong câu lệnh IF ... Khi tôi thực hiện một Quick Watch với các biểu thức sau: Tôi thấy (region == null) return false, AND (region! = Null) trả về false quá ... tại sao và như thế nào?

Cập nhật

Có người chỉ ra rằng đối tượng là == và = quá tải:

public static bool operator ==(Region r1, Region r2) 
    { 
     if (object.ReferenceEquals(r1, null)) 
     { 
      return false; 
     } 
     if (object.ReferenceEquals(r2, null)) 
     { 
      return false; 
     } 

     return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id); 
    } 


    public static bool operator !=(Region r1, Region r2) 
    { 
     if (object.ReferenceEquals(r1, null)) 
     { 
      return false; 
     } 
     if (object.ReferenceEquals(r2, null)) 
     { 
      return false; 
     } 
     return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id); 
    } 

Trả lời

28

Toán tử == và/hoặc! = Có bị quá tải cho lớp của đối tượng vùng không?

Bây giờ mà bạn đã đăng mã cho quá tải:

Các quá tải có lẽ nên trông giống như sau (mã lấy từ các quảng cáo được thực hiện bởi Jon SkeetPhilip Rieck):

public static bool operator ==(Region r1, Region r2) 
{ 
    if (object.ReferenceEquals(r1, r2)) { 
     // handles if both are null as well as object identity 
     return true; 
    } 

    if ((object)r1 == null || (object)r2 == null) 
    { 
     return false; 
    }   

    return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id); 
} 

public static bool operator !=(Region r1, Region r2) 
{ 
    return !(r1 == r2); 
} 
+0

Tôi chỉ nhận ra rằng tôi đã == và! = Quá tải! –

+0

Tôi nghĩ ai đó đã phạm sai lầm trong phần! =, Tôi sẽ kiểm tra điều đó! Thx cho gợi ý. –

+0

Đúng, quá tải sai - nếu bạn sao chép mã hoặc giải thích từ bài đăng của tôi bên dưới, tôi sẽ xóa bài đăng của mình –

3

Điều này đôi khi có thể xảy ra khi bạn có nhiều chủ đề làm việc với cùng một dữ liệu. Nếu trường hợp này xảy ra, bạn có thể sử dụng khóa để ngăn chúng rối tung với nhau.

+0

Thx, nhưng lý do thực sự là == và! = Không được quá tải tốt. Nhưng câu trả lời của bạn có thể đúng. –

16

Những quá tải toán tử bị hỏng.

Thứ nhất, nó giúp cuộc sống dễ dàng hơn nhiều nếu! = Được triển khai bằng cách chỉ cần gọi == và đảo ngược kết quả.

Thứ hai, trước khi kiểm tra vô hiệu trong == cần có:

if (object.ReferenceEquals(r1, r2)) 
{ 
    return true; 
} 
+0

OK Tôi sẽ thực hiện sửa đổi sau vài phút. –

0

Vậy là nó rằng những kiểm tra sau đây là không đúng:

public static bool operator !=(Region r1, Region r2) 
{ 
    if (object.ReferenceEquals(r1, null)) 
    { 
     return false; 
    } 
    if (object.ReferenceEquals(r2, null)) 
    { 
     return false; 
    } 
... 
+0

Có - bạn cần kiểm tra thêm trước, để giải thích cho trường hợp r1 và r2 là rỗng. Kiểm tra câu trả lời của tôi. (Điều này cũng tối ưu hóa trường hợp mà r1 và r2 đều không null, nhưng hãy tham khảo cùng một đối tượng.) –

7

Cả hai quá tải là không chính xác

public static bool operator ==(Region r1, Region r2) 
    { 
     if (object.ReferenceEquals(r1, null)) 
     { 
      return false; 
     } 
     if (object.ReferenceEquals(r2, null)) 
     { 
      return false; 
     } 

     return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id); 
    } 

nếu r1 Và r2 là rỗng, thử nghiệm đầu tiên (đối tượng.ReferenceEquals (r1, null)) sẽ trả về false, mặc dù r2 cũng là rỗng.

thử

//ifs expanded a bit for readability 
public static bool operator ==(Region r1, Region r2) 
    { 
     if((object)r1 == null && (object)r2 == null) 
     { 
      return true; 
     } 
     if((object)r1 == null || (object)r2 == null) 
     { 
      return false; 
     }   
     //btw - a quick shortcut here is also object.ReferenceEquals(r1, r2) 

     return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id); 
    } 
+0

Tôi đang thử nghiệm. cho tôi 2 phút –

+0

Điều này đang hoạt động !!!!!!!! Thx bạn sẽ có được của tôi "chấp nhận câu trả lời" nhưng ai đó tìm thấy lý do đầu tiên và bạn đã làm thế nào :) –

0

Có một khả năng mà bạn cần phải nhấp vào biểu tượng làm mới bên cạnh các thông số mà bạn đang xem. VS cố gắng theo kịp hiệu suất trong khi không đánh giá mọi câu lệnh/tham số. Hãy xem xét để đảm bảo, trước khi bạn bắt đầu thực hiện thay đổi đối với những địa điểm không liên quan.

2

Để so sánh bình đẳng của một loại "T", quá tải các phương pháp:

int GetHashCode() //Overrides Object.GetHashCode 
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed 
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to 
static bool operator ==(T x, T y) 
static bool operator !=(T x, T y) 

loại cụ thể mã so sánh của bạn nên được thực hiện ở một nơi: loại an toàn phương pháp giao diện IEquatable<T>Equals(T other). Nếu bạn so sánh với loại khác (T2), hãy thực hiện IEquatable<T2> và đặt mã so sánh trường cho loại đó bằng Equals (T2 khác).

Tất cả các phương thức và toán tử quá tải phải chuyển tiếp nhiệm vụ so sánh bình đẳng đến phương pháp thể hiện Equals (T khác) chính, như vậy hệ thống phân cấp phụ thuộc sạch sẽ được duy trì và đảm bảo nghiêm ngặt hơn ở mỗi cấp để loại bỏ dự phòng và không cần thiết phức tạp.

bool Equals(object other) 
{ 
    if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement 
     return Equals((T)other)); //forward to IEquatable<T> implementation 
    return false; //other is null or cannot be compared to this instance; therefore it is not equal 
} 

bool Equals(T other) 
{ 
    if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals 
     return false; 
    //if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check 
     //return true; 
    return field1.Equals(other.field1) && 
      field2.Equals(other.field2); //compare type fields to determine equality 
} 

public static bool operator ==(T x, T y) 
{ 
    if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals 
     return x.Equals(y); //forward to type-safe Equals on non-null instance x 
    if ((object)y != null) 
     return false; //x was null, y is not null 
    return true; //both null 
} 

public static bool operator !=(T x, T y) 
{ 
    if ((object)x != null) 
     return !x.Equals(y); //forward to type-safe Equals on non-null instance x 
    if ((object)y != null) 
     return true; //x was null, y is not null 
    return false; //both null 
} 

Thảo luận:

Việc thực hiện trước centralizes loại cụ thể (ví dụ: bình đẳng trường) so với cuối năm việc thực hiện IEquatable<T> cho các loại. Các toán tử ==!= có triển khai song song nhưng ngược lại. Tôi thích điều này hơn có một tham chiếu khác, chẳng hạn như có một cuộc gọi phương thức bổ sung cho người phụ thuộc. Nếu nhà điều hành != chỉ đơn giản gọi nhà điều hành ==, thay vì cung cấp toán tử hoạt động như nhau, thì bạn cũng có thể chỉ cần sử dụng !(obj1 == obj2) và tránh cuộc gọi phương thức bổ sung. Việc so sánh với bản thân được bỏ ra từ toán tử bằng và triển khai IEquatable<T> vì nó có thể giới thiệu 1. overhead không cần thiết trong một số trường hợp và/hoặc 2. hiệu suất không nhất quán tùy thuộc vào mức độ thường xuyên của một cá thể so với chính nó trường hợp. Một thay thế tôi không thích, nhưng nên đề cập đến, là để đảo ngược thiết lập này, tập trung mã bình đẳng kiểu cụ thể trong toán tử bình đẳng thay vào đó và có phương thức Equals phụ thuộc vào điều đó. Sau đó, người ta có thể sử dụng phím tắt của ReferenceEquals(obj1,obj2) để kiểm tra tính bình đẳng tham chiếu và bình đẳng bằng không như Philip đã đề cập trong bài trước, nhưng ý tưởng đó là gây hiểu nhầm. Có vẻ như bạn đang giết hai con chim bằng một viên đá, nhưng thực tế bạn tạo ra nhiều công việc hơn - sau khi xác định các đối tượng không phải là cả null lẫn cùng một cá thể, bạn sẽ phải thêm vào để kiểm tra xem mỗi cá thể là null. Trong thực hiện của tôi, bạn kiểm tra cho bất kỳ cá thể duy nhất là null chính xác một lần. Vào thời điểm phương thức Equals được gọi, nó đã bị loại trừ rằng đối tượng đầu tiên được so sánh là null, vì vậy tất cả những gì còn lại cần làm là kiểm tra xem đối tượng kia có rỗng không. Vì vậy, sau nhiều nhất hai so sánh, chúng tôi nhảy trực tiếp vào lĩnh vực kiểm tra, bất kể phương pháp chúng tôi sử dụng (Equals(object),Equals(T),==,!=). Ngoài ra, như tôi đã đề cập, nếu bạn thực sự so sánh và phản đối phần lớn thời gian, thì bạn có thể thêm kiểm tra đó vào phương thức Bằng ngay trước khi đi sâu vào các so sánh trường. Điểm bổ sung cuối cùng là bạn vẫn có thể duy trì phân cấp dòng/phụ thuộc mà không cần giới thiệu một kiểm tra dự phòng/vô ích ở mọi cấp độ.

0
bool comp; 
if (object.IsNullOrEmpty(r1)) 
{ 
    comp = false; 
} 

if (object.IsNullOrEmpty(r2)) 
{ 
    comp = false; 
} 
return comp; 
+1

// nó có thể giúp bạn, hoặc giúp đỡ bất cứ ai cần nó – fernando

+2

Xin vui lòng không chỉ cung cấp câu trả lời mã. –