2015-02-11 25 views
15

Tôi có hai khách hàng mà tạo IPAddress trường từ cùngbyte[] và gửi nó đến máy chủ qua WCF (sử dụng DataContractSerializer).Hai bình đẳng trường IPv6 IPAddress trở GetHashCode khác nhau kết quả

Trên máy chủ, các trường hợp IPAddress này được chèn làm khóa trong từ điển nhưng vì lý do nào đó chúng được thêm làm các khóa khác nhau.

Khi đăng nhập, tôi thấy chúng bằng nhau nhưng GetHashCode trả về các kết quả khác nhau.

var client1Address = // sent from client1 
var client2Address = // sent from client2 

Console.WriteLine(client1Address.Equals(client2Address)); 
Console.WriteLine(client1Address.GetHashCode().Equals(client2Address.GetHashCode())); 

Output:

true 
false 

Làm thế nào có thể bằng IPAddress trường hợp trở lại khác nhau GetHashCode kết quả?

Trả lời

16

Các GetHashCode implementation của IPAddress cho IPv6 là:

if (m_HashCode == 0) 
{ 
    m_HashCode = StringComparer.InvariantCultureIgnoreCase.GetHashCode(ToString()); 
    return m_HashCode; 
} 

Để tránh tính lại mã băm một lần nữa và một lần nữa, họ đang lưu trữ kết quả trong một thành viên tư nhân. Thành viên cá nhân này sau đó được đăng trên máy chủ từ xa.

Điều này là, StringComparer.InvariantCultureIgnoreCase.GetHashCode(ToString()) trả về các kết quả khác nhau trên các phiên bản hệ điều hành khác nhau và kể từ m_HashCode cũng được tuần tự hóa, máy chủ không tính toán lại.

Kết quả này trong hai trường hợp IPAddress giống hệt nhau với kết quả khác nhau GetHashCode.

Tôi nghĩ rằng thành viên riêng m_HashCode phải được đánh dấu là [NonSerialized], điều này sẽ gây ra GetHashCode để tạo lại mã băm cục bộ và chính xác.

Như một giải pháp thay thế, tôi đã can thiệp vào quá trình tuần tự hóa và được tuần tự hóa thành byte[].


Here's the bug on VisualStudio connect. Liên kết này đã chết vì lỗi đã bị đóng vì những lý do sau:

"Cảm ơn bạn đã báo cáo vấn đề này. Rất tiếc, nhóm của chúng tôi không thể giải quyết vấn đề này do các mục ưu tiên cao hơn khác. đối với nội dung được tuần tự hóa của một loại dẫn đến nguy cơ vi phạm các ứng dụng đã phụ thuộc vào hành vi đó. "

+2

Thú vị tìm thấy. – Lloyd

+0

Tôi tin rằng kịch bản chính xác này được cảnh báo trong .NET GetHashCode và String Compare và String dựa trên các toán tử Equality. Tôi không nghĩ rằng đây là một lỗi trong đó GetHashCode là một tài sản thời gian chạy NET tư nhân hiệu quả mà không nên được sử dụng trực tiếp bởi mã của chúng tôi ở cấp ứng dụng. Vì IPV6 là một điều được biết, tôi sẽ sử dụng chính địa chỉ đó là Hash Code hoặc Equality operator. Nhưng tôi sẽ làm so sánh thực tế ở mức byte cho một giá trị được định dạng. Tương tự như cách thức hoạt động của guid. “ABCD-123” = “abcd123” Từ góc nhìn thiết kế Tôi nghĩ đó là một lỗi. Họ có thể thay đổi nó ngay bây giờ không? –

+4

@SqlSurfer 'GetHashCode' không phải là riêng tư và nó không được sử dụng trực tiếp. Khi bạn sử dụng 'IPAddress' làm khóa từ điển, nó sử dụng' GetHashCode' trong nội bộ. Lỗi ở đây là mã băm được lưu trữ và được tuần tự hóa khi không được. – i3arnon

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