2012-07-10 53 views
7

Vì phạm vi kiểm tra (đơn vị) của tôi vẫn còn khá thấp, thật không may, tôi phải tìm nhiều lỗi theo cách khó. Vì vậy, trong quá trình tái cấu trúc, tôi phụ thuộc rất nhiều vào việc kiểm tra kiểu của trình biên dịch C#.An toàn loại an toàn()

Hôm nay, tôi đã sửa lỗi được giới thiệu trong khi tái cấu trúc bằng cách thiếu một dòng với x.Equals(aThingWrappingOriginalThing). Vì nó là bool Equals(object T), trình biên dịch không phàn nàn. Tuy nhiên, 90% thời gian tôi sử dụng trực tiếp Equals() (thay vì thông qua BCL), tôi dự định so sánh một cách hợp lý các đối tượng cùng loại.

Bây giờ tôi tự hỏi tại sao tôi chưa bao giờ thấy ai đó quảng cáo phiên bản loại an toàn Equals() cho các tình huống như vậy (trong C#). Có cách nào tốt nhất cho việc này không?

Tôi bị cám dỗ để sử dụng một phương pháp mở rộng cho những comparisions, như vậy:

public static bool SafeEquals<T>(this T a, T b) 
{ 
    if (a == null) return b == null; 
    return a.Equals(b); 
} 
public static bool SafeEquals<X>(this IEquatable<X> a, IEquatable<X> b) 
{ 
    if (a == null) return b == null; 
    return a.Equals(b); 
} 

những có thể được tối ưu hóa?

Dưới đây là các bài viết trên blog chỉ về chủ đề tôi thấy, đối với java: http://rickyclarkson.blogspot.com/2006/12/making-equalsobject-type-safe.html

+0

Dưới đây là một số thông tin cơ bản về chủ đề: http://blogs.msdn.com/b/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx – Vlad

Trả lời

5

Bạn đang tìm kiếm

EqualityComparer<T>.Default.Equals(x,y); 

này hỗ trợ IEquatable<T> (nếu được thực hiện), nếu không sử dụng các tiềm năng-boxing Equals(object); nó hỗ trợ các lớp và cấu trúc, với hành vi null dự kiến ​​cho cả hai, bao gồm hỗ trợ cho Nullable<T> (không có quyền anh).

+0

Cảm ơn, âm thanh tuyệt vời. Liệu nó có làm tổn thương hiệu suất để quấn nó vào một phương pháp mở rộng? Nó sẽ được inlined? – Equalizer

+0

@Equalizer phương pháp mở rộng là tĩnh cuộc gọi, vì vậy: không thực sự, không có. Nó không có khả năng bị nghiêng vì .Default là một cá thể của một số triển khai cụ thể, tùy thuộc vào chiến lược được sử dụng. Quyết định/phản hồi chỉ được thực hiện một lần cho mỗi T, vì vậy nó được lưu trữ - nhưng không được gạch chân. –

2

Những gì tôi thấy có vẻ tốt với tôi.

2 cent của tôi: Tôi nghĩ rằng nó sẽ đơn giản hơn để bỏ qua kiểm tra null, và sử dụng này:

public static bool SafeEquals<T>(this T a, T b) 
{ 
    return object.Equals(a, b); 
} 

Có rất ít trường hợp trong đó sẽ đi chệch khỏi hành vi dự định. Một trong số đó là khi Equals trả về false khi cả hai đối tượng đều là cùng một đối tượng (không bao giờ xảy ra).

Để tham khảo, dưới đây là số biên dịch object.Equals để bạn có thể tự mình xem điều gì sẽ xảy ra.

public static bool Equals(object objA, object objB) 
{ 
    return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB))); 
} 
+0

'Object. Bằng kiểm tra nếu cả hai đều trỏ đến cùng một dữ liệu trên heap, không phải nếu chúng giống nhau. –

+0

@Kendall thực hiện đầu tiên ở đây chỉ là một wrapper xung quanh object.Equals, cho rằng, tại sao không chỉ cho phép người tiêu dùng gọi object.Equals cho tất cả những gì nó có giá trị – Jason

+0

@ColeJohnson Có thể theo mặc định. Nhưng có sự khác biệt giữa 'Equals' và' ReferenceEquals' –