SORU
20 Ocak 2009, Salı


C GetHashCode Kuralları#

# 3.0 Temel C okudum .NET 3.5 kitabı:

() GetHashCode’belirli bir nesnenin ömrü boyunca s döndürür olmalıdır sabit (aynı değer), bu nesnenin verilerine değişse bile. Birçok doğduğunda önbellek bu yöntemi uygulamak için geri dönmesi gerekir.

Bu geçerli bir kılavuzdur?

Birkaç yerleşik türleri denedim .NET ve onlar böyle bir davranış değildi.

CEVAP
13 Temmuz 2010, Salı


Uzun zaman oldu, ama yine de hala bu soruya doğru bir cevap vermek gerekirse, neden ve nasıl hakkında açıklamalar dahil olduğunu düşünüyorum. En iyi cevap şimdiye kadar bir MSDN exhaustivly - kendi kurallarını yapmaya çalışmayın gerekçe göstererek, MS adamlar ne yaptıklarını biliyorlardı.

Ama öncelikle: Soruda ifade edildiği gibi, Kılavuz yanlış.

Şimdi neden ikisi de var

İlk neden: Eğer hashcode eğer kendisi değişiklikleri nesne bile değişmez bir nesnenin ömrü boyunca bir şekilde hesaplanmış,,, kıracak daha eşittir-sözleşme.

Unutmayın: Eğer iki nesne eşit olarak karşılaştırmak", her nesne için GetHashCode yöntemi aynı değeri döndürür. Eğer iki nesne eşit karşılaştırma değil, ancak iki nesne için GetHashCode yöntem farklı değerlere dönmek yok."

İkinci cümleyi sık olarak yanlış olduğunu "tek kural nesne oluşturma sırasında, eşit nesnelerin hashcode eşit olmalıdır". Neden olduğunu bilmiyorum, ama çoğu cevap burada özü gibi.

İki nesne adı eşittir yönteminde kullanılan bir ad içeren bir düşünün: Aynı adı ->aynı şey. Bir Örnek Oluşturun: Ad = Joe Örnek B Oluşturun: Name = Peter

Hashcode ve Hashcode Bir B büyük olasılıkla aynı olmayacaktır. Şimdi örnek B Adı Joe değiştiğinde ne olacak?

Soru yönergeye göre, B hashcode değişiklik olmaz. Bu sonucu şöyle olacaktır: A Eşittir B) ==>gerçek Aynı zamanda ama: () A. GetHashCode == B. GetHashCode() ==>yanlış.

Ama tam olarak bu davranışları açıkça equals ve hashcode-sözleşme ile yasaklanmıştır.

İkinci neden: Bu hashcode değişiklikleri karma listeler ve diğer nesnelerin hashcode kullanarak bozulan - elbette - doğru olsa da, tersi de geçerlidir. Değil değişen hashcode olacak, en kötü durum almak sağlaması listeleri, bir sürü farklı nesneler aynı hashcode ve bunun olması içinde aynı hash bin olduğunda nesneleri başlatılmış bir standart değer, örneğin.


Şimdi nasıl geliyor Evet, ilk bakışta bir çelişki var gibi görünüyor - her iki şekilde de, kodu kıracak. Ama sorun ne değişti ya da değişmedi hashcode nereden geliyor.

Sorunların kaynağı iyi MSDN tanımlanır:

Msdn'den bu karma tablo giriş:

Anahtar nesneleri sürece sabit olmalıdır Bu anahtarları olarak kullanıldıkları gibi Karma tablo.

Bu demek oluyor:

Herhangi bir nesne oluşturur hashvalue değiştirmeniz gerekir hashvalue, ne zaman nesneyi değiştirir, ama hayır - Kesinlikle hayır - izin herhangi bir değişiklik kendisini, zaman içinde kullanılan bir karma tablo (veya başka bir Hash kullanarak nesne, elbette).

İlk nasıl En kolay yolu tabii ki, bu değişken normal copys olarak oluşturulacak hashtables kullanımı, sadece sabit nesneleri tasarım için olacak gerekli nesneleri. Değişmez nesneler içinde, değişmez olduğu obviusly, hashcode önbellek için sorun değil.

İkinci nasıl Ya da nesne bir "karma şimdi"bayraklı, emin olun tüm nesne veri özel, onay bayrağı tüm fonksiyonları değiştirebilir nesneleri veri ve bir istisna atar veri eğer bir değişiklik yapılamaz (yani bayrağı ayarlanmış). Herhangi bir karma alandaki nesne koyduğunuzda, bayrak, ve - de - artık gerekli olduğunda bayrağı, kullanmak için emin olun. Kullanım kolaylığı için, bayrak içinde otomatik olarak ayarlamanızı tavsiye ederim "GetHashCode" yöntem - unutulmuş olamaz bu şekilde. Ve bir açık çağrı "" yöntemi programcı düşünmek zorunda kalacak, emin olun, hava ya şimdi. nesneleri verileri değiştirmek için izin verilmez ResetHashFlag

Peki, ne dedi de: Orada durumlarda nerede olanaklıdır nesne ile değişken data, nerede hashcode rağmen değişmeden, zaman nesneleri veri değişti, olmadan ihlal equals ve hashcode-sözleşme.

Bu eşittir-yöntem değişken veri olarak değil, ancak gerektirir. Bu yüzden, eğer yazdığım bir nesne oluşturmak ve bir GetHashCode yöntemi bu mu hesaplamak için bir değer sadece bir kere ve mağaza içindeki nesneyi geri daha sonra çağırır, sonra ben, yine: kesinlikle olmalı, create a Eşittir yöntemi kullanacak saklı değerleri için karşılaştırma, böylece A Eşittir B) asla değişmez yanlış için de doğrudur. Aksi takdirde sözleşme kırılır. Bunun sonucu da genellikle bu yöntem hiç mantıklı değil Eşit olacak - orijinal referans eşit değil, ama ne de eşit bir değerdir. Bazen, bu davranışlara yönelik olabilir (yani müşteri kayıtları), ama genellikle değil.

Yani, sadece GetHashCode sonucu değiştirmek, zaman, nesne, veri değişiklikleri, ve eğer kullanım nesnenin içinde karma listeler veya nesneleri amaçlanan (veya mümkün) sonra nesne ya değişmez ya da oluşturmak bir salt okunur bayrağı kullanmak için ömür boyu bir karma listesini içeren nesne.

(Bu arada: bu C değil Tüm# oder .NET özel - nesne listesinde ise nesneleri tanımlayıcı veri değişim asla herhangi bir dizine listesindeki tüm karma tablo uygulamaları doğal olarak, ya da daha genel olarak. Beklenmeyen ve önceden tahmin edilemeyen davranışlar eğer bu kural hatası varsa ortaya çıkar. Bir yerlerde, liste içindeki tüm öğeleri izlemek ve otomatik yeniden dizin oluşturmaya liste yapın, liste uygulamaları, olabilir - ama bu performans şüphesiz en korkunç olur.)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BrandonHarrisWalker

    BrandonHarri

    27 Kasım 2006
  • michal lelkowski

    michal lelko

    9 Temmuz 2006
  • The Pet Collective

    The Pet Coll

    5 Ocak 2012