2010-11-21 57 views
28

Như bạn đã biết, GetHashCode trả về một giá trị bán duy nhất có thể được sử dụng để xác định một cá thể đối tượng trong một bộ sưu tập. Để thực hành tốt, bạn nên ghi đè phương pháp này và thực hiện phương pháp của riêng mình.Ghi đè GetHashCode

Câu hỏi của tôi là - bạn có ghi đè phương thức này khi làm việc trên các đối tượng tùy chỉnh không? Nếu vậy, bạn sử dụng thuật toán nào để tạo ID duy nhất?

Tôi đã suy nghĩ về việc tạo GUID và sau đó nhận dữ liệu nguyên từ số nhận dạng đó.

+2

Đọc [câu hỏi này] (http: // stackoverflow.com/questions/263400/what-is-the-best-algorithm-cho-an-an-ghi đè-hệ thống-đối tượng-gethashcode) và câu trả lời của nó. Nó phác thảo một triển khai mã băm tốt. Ngoài ra còn có một cuộc thảo luận tốt về việc kiểm soát 'GetHashCode' cho các đối tượng có thể thay đổi được tại đây (http://stackoverflow.com/questions/873654/overriding-gethashcode-for-mutable-objects-c). – adrianbanks

+7

Tôi không biết "bán duy nhất" có nghĩa là ... giá trị là duy nhất hoặc không, và một mã băm không phải là duy nhất. Do đó nó không cho phép bạn xác định một đối tượng trong danh sách. Và đó không phải là "thực hành tốt" để ghi đè 'GetHashCode', đó là điều bạn làm khi bạn * cần * (ví dụ: sử dụng đối tượng làm khóa trong từ điển), không phải vì bạn nghĩ đó là một thực hành tốt. –

+0

Sử dụng đối tượng làm khóa có thể được coi là xác định đối tượng trong bộ sưu tập - đó chính xác là lý do tôi tìm kiếm đầu vào về thuật toán tốt nhất để tạo mã định danh là gì. Từ các ID bán duy nhất: http://www.west-wind.com/Weblog/posts/4741.aspx –

Trả lời

24

Khi bạn ghi đè GetHashCode(), bạn cũng cần ghi đè Equals(), operator==operator!=. Và rất cẩn thận để đáp ứng tất cả các yêu cầu cho những phương pháp đó.

Nguyên tắc là here on MSDN. Trích dẫn quan trọng nhất:

Bạn không nên ghi đè toán tử == bằng các loại không thay đổi.

+0

Từ những gì tôi hiểu, điều đó sẽ không có ý nghĩa bởi vì, tốt, đối tượng sẽ không thay đổi trạng thái của nó . –

+0

Điều gì sẽ không có ý nghĩa? –

+0

Ghi đè toán tử ==. Các chuỗi –

-2

Nói chung tôi sử dụng GetHashCode tổng hợp từ các thuộc tính thành phần của lớp. Ví dụ.

public class Test 
{ 
    public string Text { get; set; } 
    public int Age { get; set; } 

    public override GetHashCode() 
    { 
    int result = 
     string.IsNullOrEmpty(Text) ? 0 : Text.GetHashCode() 
     + Age.GetHashCode(); 

    return result; 
    } 
} 
+5

Đây không phải là một cách rất goo để làm điều đó, xem http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode –

+0

Nói chung thêm không tốt cho việc tạo một hashcode phức hợp. Nhưng trong ví dụ cụ thể này tôi thấy không có vấn đề với nó. Nhưng tất nhiên, trọng số GetHashCode mà không có trọng số bằng nhau không có ý nghĩa gì nhiều. – CodesInChaos

+0

Vâng, bạn học điều gì đó mỗi ngày! –

1

Khi sử dụng cá nhân, tôi chỉ ghi đè khi ghi đè bằng phương pháp. Nói chung, tôi làm điều này cho các đối tượng tôi biết rằng tôi có thể chạy một LINQ to Objects truy vấn trên, hoặc một số hoạt động so sánh khác.

Tôi thường trả lại, nếu nói một đối tượng LINQ to SQL hoặc đối tượng DTO, giá trị khóa chính. Dù bạn quay trở lại, nếu bạn không lưu trữ giá trị cục bộ, nó có thể tạo ra kết quả không mong muốn.

HTH.

0

bạn chỉ cần ghi đè GetHashCode nếu bạn đang ghi đè Bằng. GetHashCode mặc định được thực thi bởi thời gian chạy theo cách tương tự như bạn muốn thực hiện - mọi đối tượng đều có một trường ẩn được gán bởi thời gian chạy.

How to override GetHashCode

Trên thực tế IDE của bạn nên làm điều này cho bạn - khi bạn gõ "ghi đè GetHashCode" IDE nên tạo mã boilerplate này. Visual Studio không làm điều đó nhưng SharpDevelop.

+0

Việc cài đặt mặc định của phương thức GetHashCode không đảm bảo các giá trị trả về duy nhất cho các đối tượng khác nhau. Do đó, việc thực hiện mặc định của phương thức này không được sử dụng như một định danh đối tượng duy nhất cho các mục đích băm. Từ: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx – brain

+0

trong VS người ta phải sử dụng đoạn mã 'equals' thay vì – CodesInChaos

+1

@brain - tôi đọc nó. Nó có nghĩa là bạn nên luôn luôn ghi đè GetHashCode khi bạn muốn lưu trữ các đối tượng của bạn trong một từ điển? Tôi không nghĩ vậy - hầu như không ai làm điều này. Việc triển khai mặc định hoạt động tốt cho các mục đích của từ điển. Nó không hoàn hảo, nhưng tốt: http://stackoverflow.com/questions/750947/net-unique-object-identifier –

1

Tôi thường ghi đè phương pháp kiểm tra mã băm và bình đẳng cho các lớp dữ liệu (nghĩa là các lớp có nghĩa ngữ nghĩa giá trị). Hãy xem câu hỏi this để thực hiện phổ biến. Nếu bạn ghi đè lên quá mức hashcode bằng. Sử dụng GUID là một ý tưởng khá khủng khiếp vì bạn muốn hai đối tượng khác nhau nhưng có cùng giá trị để có cùng mã băm và bằng để trả về giá trị true.

27

Nếu bạn sử dụng chức năng chia sẻ lại, nó có thể tạo cơ chế GetHashCode(), Bằng và toán tử cho bạn.

Truy cập menu này bằng cách nhấn Alt + Chèn.

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html

+1

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html – Deinonychus

+2

Cách dễ dàng hơn không chèn quá nhiều bản mẫu và luôn cập nhật khi lớp học của bạn thay đổi: http: //eamonnerbonne.github .io/ValueUtils/ –

+0

Vì bất kỳ lý do gì alt + chèn không mở trình đơn chia sẻ lại của tôi, nhưng tôi có thể sử dụng menu: Resharper -> Edit -> Generate Code ... –