Để 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ử ==
và !=
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 độ.
Tôi chỉ nhận ra rằng tôi đã == và! = Quá tải! –
Tôi nghĩ ai đó đã phạm sai lầm trong phần! =, Tôi sẽ kiểm tra điều đó! Thx cho gợi ý. –
Đú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 –