2009-12-10 28 views
15

tôi đã xác định các giao diện sauLàm cách nào để ghi đè toán tử == cho Giao diện trong C#?

public interface IHaveAProblem 
{ 
    string Issue { get; set; } 
} 

Và đây là việc thực hiện các IHaveAProblem

public class SomeProblem : IHaveAProblem 
{ 
    public string Issue { get; set; } 

    public override bool Equals(object obj) 
    { 
     SomeProblem otherObj = obj as SomeProblem; 

     if (otherObj == null) 
     { 
      return false; 
     } 

     return this.Issue == otherObj.Issue; 
    } 

    public override int GetHashCode() 
    { 
     return base.GetHashCode(); 
    } 

    public static bool operator ==(SomeProblem rhs, SomeProblem lhs) 
    { 
     // Null check 
     if (Object.ReferenceEquals(rhs, null) || Object.ReferenceEquals(lhs, null)) 
     { 
      if (Object.ReferenceEquals(rhs, null) && Object.ReferenceEquals(lhs, null)) 
      { 
       // Both are null. They do equal each other 
       return true; 
      } 

      // Only 1 is null the other is not so they do not equal 
      return false; 
     } 

     return rhs.Equals(lhs); 
    } 

    public static bool operator !=(SomeProblem rhs, SomeProblem lhs) 
    { 
     // Null check 
     if (Object.ReferenceEquals(rhs, null) || Object.ReferenceEquals(lhs, null)) 
     { 
      if (Object.ReferenceEquals(rhs, null) && Object.ReferenceEquals(lhs, null)) 
      { 
       // Both are null. They do equal each other 
       return false; 
      } 

      // Only 1 is null the other is not so they do not equal 
      return true; 
     } 

     return !rhs.Equals(lhs); 
    } 
} 

Khi tôi sử dụng đối tượng tôi có thể có được kết quả chính xác cho các == so sánh.

SomeProblem firstTest = new SomeProblem() 
    { 
     Issue = "Hello World" 
    }; 

SomeProblem secondTest = new SomeProblem() 
    { 
     Issue = "Hello World" 
    }; 

// This is true 
bool result = firstTest == secondTest; 

Tuy nhiên khi tôi cố gắng để so sánh các giao diện nó đang làm một bộ nhớ so sánh chứ không phải là toán tử == trên SomeProblem

IHaveAProblem firstProblem = new SomeProblem() 
    { 
     Issue = "Hello World" 
    }; 

IHaveAProblem secondProblem = new SomeProblem() 
    { 
     Issue = "Hello World" 
    }; 

Có thể có giao diện sử dụng == trên SomeProblem hơn một bộ nhớ so sánh?

Tôi biết mình có thể làm firstProblem.Equals(secondProblem) và nhận kết quả phù hợp, tuy nhiên tôi đang tạo một tác phẩm khung và tôi sẽ không biết cách nó được sử dụng cuối cùng. Tôi nghĩ == sẽ hoạt động chính xác.

+1

Có một cuộc thảo luận khá kỹ lưỡng về điều này tại đây. Tác giả dường như đã có một chút thời điểm bóng đèn liên quan đến một số giả định mà tôi nghĩ rằng bạn chia sẻ: http://stackoverflow.com/questions/728434/operator-overloading-with-interface-based-programming-in-c –

Trả lời

22

Nhà điều hành == là tĩnh. Bạn không thể định nghĩa các phương thức tĩnh cho các giao diện trong C#. Ngoài ra, đối với tất cả các toán tử ít nhất một trong các kiểu đối số cần phải có cùng loại với lớp được định nghĩa, do đó: Không có quá tải toán tử cho giao diện: (

Điều bạn có thể làm là sử dụng lớp trừu tượng thay thế -. và xác định các nhà điều hành có Một lần nữa, các nhà điều hành có thể kHÔNG ảo (kể từ khi phương pháp tĩnh không thể ảo ...)

[Sửa, lý do thấy nhận xét.]

+1

Có thể Tôi nhận được đoạn cuối cùng sai, nhưng tôi nghĩ rằng đó là sai. Tôi sẽ nói: "Việc thực hiện mặc định của toán tử (trên các kiểu tham chiếu và giao diện) hoạt động như phương thức' ReferenceEquals' được cung cấp bởi 'Object'. Chắc chắn không phải phương thức' Equals', mà chính nó cũng mặc định tham chiếu bình đẳng (đối với kiểu tham chiếu) , nếu không được ghi đè bởi các lớp dẫn xuất), hơn nữa, các cấu trúc không có toán tử mặc định ==, mặc dù bạn có thể định nghĩa một. – thaller

0

Trong nhà khai thác C# là tĩnh và trọng tĩnh phương pháp là ... lộn xộn.

Tại sao bạn không chỉ đơn giản là ghi đè phương thức Equals() được kế thừa từ vật? Đó là khá đơn giản và bạn sẽ không phải lộn xộn với các phương pháp tĩnh ghi đè.

4

IIRC (và tôi có thể sai ở đây), giao diện C# không cho phép quá tải toán tử.

Nhưng trong trường hợp này thì không sao. Toán tử == thường ánh xạ tới bình đẳng tham chiếu. Có vẻ như bạn muốn bình đẳng giá trị, và điều đó có nghĩa là bạn muốn buộc họ ghi đè các hàm .Equals() (và do đó cũng là .GetHashCode()). Bạn làm điều đó bằng cách có giao diện của bạn kế thừa từ IEquatable().

0

Bạn đã thử triển khai IComparable chưa?

Như thế này:

public interface IHaveAProblem : IComparable 
{ 
    string Issue { get; set; } 
} 

Và sau đó trong việc thực hiện các lớp:

public class SomeProblem : IHaveAProblem 
{ 
    public string Issue { get; set; } 

    ... 

    public int CompareTo(object obj) 
    { 
     return Issue.CompareTo(((SomeProblem)obj).Issue); 
    } 
} 

Lưu ý rằng, điều này chỉ hoạt động khi bạn so sánh hai trường hợp của SomeProblem, nhưng không phải bất kỳ hiện thực khác của giao diện IHaveAProblem.

Không chắc chắn nếu có thể xảy ra NullReferenceException.

2

Tôi konw, đây là câu hỏi cũ, nhưng tất cả các ví dụ được cung cấp đều cho thấy cách so sánh hai phiên bản lớp và không ai chỉ ra cách so sánh hai phiên bản giao diện.

Trong một số trường hợp, đây là cách DRYest để so sánh giao diện.

public interface IHaveAProblem 
{ 
    string Issue { get; set; } 
} 

public class IHaveAProblemComparer : IComparer<IHaveAProblem>, IEqualityComparer<IHaveAProblem> 
{ 
    public int Compare(IHaveAProblem x, IHaveAProblem y) 
    { 
     return string.Compare(x.Issue, y.Issue); 
    } 

    public bool Equals(IHaveAProblem x, IHaveAProblem y) 
    { 
     return string.Equals(x.Issue, y.Issue); 
    } 

    public int GetHashCode(IHaveAProblem obj) 
    { 
     return obj.GetHashCode(); 
    } 
} 

Cách sử dụng?

IHaveAProblemComparer comparer = new IHaveAProblemComparer(); 

List<IHaveAProblem> myListOfInterfaces = GetSomeIHaveAProblemObjects(); 
myListOfInterfaces.Sort(comparer); // items ordered by Issue 

IHaveAProblem obj1 = new SomeProblemTypeA() { Issue = "Example1" }; 
IHaveAProblem obj2 = new SomeProblemTypeB() { Issue = "Example2" }; 

bool areEquals = comparer.Equals(obj1, obj2); // False 
Các vấn đề liên quan