2013-08-05 34 views
10

My search for a helper to correctly combine constituent hashcodes for GetHashCode() dường như thu hút sự thù địch. Tôi có ấn tượng từ các bình luận rằng một số nhà phát triển C# không nghĩ rằng bạn nên ghi đè lên GetHashCode() thường xuyên - chắc chắn một số người bình luận dường như nghĩ rằng một thư viện để giúp có được hành vi đúng sẽ là vô ích. Chức năng này được coi là đủ hữu ích trong Java cho Java community to ask for it to be added to the JDK và là now in JDK 7.Tại sao tôi nên * không * ghi đè GetHashCode()?

Có một số lý do cơ bản mà trong C# bạn không cần phải - hoặc chắc chắn không nên ghi đè GetHashCode() (và tương ứng, Equals()) thường xuyên như trong Java? Tôi thấy mình làm điều này thường xuyên với Java, ví dụ bất cứ khi nào tôi tạo ra một loại mà tôi biết tôi muốn giữ trong một HashSet hoặc sử dụng như một chìa khóa trong một HashMap (tương đương, .net Dictionary).

+1

Bạn nên ghi đè GetHashCode() khi tạo loại đại diện cho giá trị. – SLaks

+0

@Slaks như 'int',' double' và 'Point'? –

+0

Liên quan: http://stackoverflow.com/questions/2907372/why-does-c-sharp-not-implement-gethashcode-for-collections – assylias

Trả lời

1

C# có các loại giá trị tích hợp cung cấp sự bình đẳng giá trị, trong khi Java thì không. Vì vậy, việc viết mã băm của riêng bạn trong Java có thể là một điều cần thiết, trong khi thực hiện nó trong C# có thể là một tối ưu hóa sớm.

Thông thường, hãy viết loại để sử dụng làm khóa tổng hợp để sử dụng trong Từ điển/HashMap. Thông thường đối với các loại như vậy, bạn cần value equality (equivalence) as opposed to reference equality(identity), ví dụ:

IDictionary<Person, IList<Movie> > moviesByActor; // e.g. initialised from DB 
// elsewhere... 
Person p = new Person("Chuck", "Norris"); 
IList<Movie> chuckNorrisMovies = moviesByActor[p]; 

Ở đây, nếu tôi cần phải tạo một đối tượng mới của Người để làm tra cứu, tôi cần Person để thực hiện bình đẳng giá trị nếu không nó sẽ không phù hợp với mục hiện tại trong từ điển vì chúng có bản sắc khác nhau.

Để nhận được sự bình đẳng về giá trị, bạn cần ghi đè Equals()GetHashCode() bằng cả hai ngôn ngữ.

Cấu trúc của C# (loại giá trị) implement value equality cho bạn (mặc dù có thể có hiệu quả tiềm năng) và cung cấp triển khai nhất quán GetHashCode. Điều này có thể đủ cho nhu cầu của nhiều người và họ sẽ không đi xa hơn để thực hiện phiên bản cải tiến của riêng mình trừ khi các vấn đề về hiệu năng đưa ra theo cách khác.

Java không có tính năng ngôn ngữ được cài sẵn. Nếu bạn muốn tạo một kiểu có các ngữ nghĩa bình đẳng giá trị để sử dụng như một khóa tổng hợp, bạn phải thực hiện equals() và tương ứng hashCode(). (Có những người trợ giúp và thư viện của bên thứ ba để giúp bạn làm điều này, nhưng không có gì được xây dựng vào chính ngôn ngữ đó).

tôi đã mô tả C# loại giá trị là 'có khả năng không hiệu quả' để sử dụng trong một từ điển vì:

0

Nếu đối tượng của bạn đại diện cho giá trị hoặc loại, thì bạn NÊN ghi đè GetHashCode() cùng với Bằng. Tôi không bao giờ ghi đè mã băm cho các lớp điều khiển, như "Ứng dụng". Mặc dù tôi thấy không có lý do tại sao thậm chí ghi đè GetHashCode() trong những trường hợp đó sẽ là một vấn đề vì chúng sẽ không bao giờ được đặt ở vị trí can thiệp vào việc thu thập chỉ mục hoặc so sánh.

Ví dụ:

public class ePoint : eViewModel, IEquatable<ePoint> 
{ 
    public double X; 

    public double Y; 

    // Methods 

    #region IEquatable Overrides 

    public override bool Equals(object obj) 
    { 
     if (Object.ReferenceEquals(obj, null)) { return false; } 

     if (Object.ReferenceEquals(this, obj)) { return true; } 

     if (!(obj is ePoint)) { return false; } 

     return Equals((ePoint)obj); 
    } 

    public bool Equals(ePoint other) 
    { 
     return X == other.X && Y == other.Y; 
    } 

    public override int GetHashCode() 
    { 
     return (int)Math.Pow(X,Y); 
    } 

    #endregion 
+1

Cảm ơn. Điều này cũng đúng với Java như của C#. Nó không giải thích nếu có một lý do cụ thể mà điều này là cần thiết ít thường xuyên hơn trong C# vs Java. – bacar

+0

Nếu nó giống nhau, thì trong trường hợp nào khác java yêu cầu nó? – KindaFearless

0

Tôi đã viết một helper class để thực hiện GetHashCode(), Equals(), và CompareTo() sử dụng ngữ nghĩa giá trị từ một mảng bất động sản.

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