SORU
23 Mayıs 2012, ÇARŞAMBA


Null karma kodu her zaman sıfır olmalıdır .NET

System.Collections.Generic.HashSet<> set bir üyesi olarak null kabul gibi koleksiyonlar göz önüne alındığında, bir null karma kodu ne olması gerektiğini sorabilir. Çerçeve 0 kullanır gibi görünüyor:

// nullable struct type
int? i = null;
i.GetHashCode();  // gives 0
EqualityComparer<int?>.Default.GetHashCode(i);  // gives 0

// class type
CultureInfo c = null;
EqualityComparer<CultureInfo>.Default.GetHashCode(c);  // gives 0

Bu (küçük) null çeteleler ile sorunlu olabilir. Biz tanımlarsanız

enum Season
{
  Spring,
  Summer,
  Autumn,
  Winter,
}

sonra Nullable<Season> (Season?) denilen sadece beş değerler alabilir, ama ikisi, yani null Season.Spring, aynı karma kodu var.

Cazip"," eşitlik karşılaştırıcısı bu gibi: . daha iyi yazmak için

class NewNullEnumEqComp<T> : EqualityComparer<T?> where T : struct
{
  public override bool Equals(T? x, T? y)
  {
    return Default.Equals(x, y);
  }
  public override int GetHashCode(T? x)
  {
    return x.HasValue ? Default.GetHashCode(x) : -1;
  }
}

Ama null karma kodu 0 olması için bir sebep var mı?

/AYRICA EDİT:

Bazı insanlar bu Object.GetHashCode() geçersiz kılma ile ilgili olduğunu düşünüyor gibi görünüyor. Gerçekten, gerçekten değil. (Yazarlar .NET Nullable<> yapı GetHashCode() geçersiz kılma yaptıkonuyla alakasız.) Bir aradığımız olan nesne null burada yazılı kullanım GetHashCode() asla durumu idare edebilir parametresiz uygulanması.

Bu soyut yöntem EqualityComparer<T>.GetHashCode(T) uygulama veya başka bir arabirim yöntemi IEqualityComparer<T>.GetHashCode(T) uygulama ile ilgili. MSDN için bu bağlantıları oluştururken şimdi, Eğer tamamen kendi bağımsız null eğer bu yöntemleri ArgumentNullException bir atın orada diyor ki, bunu görüyorum. Bu kesinlikle MSDN'DE bir hata olmalı? Hiçbiri .NET kendi uygulamaları istisna atar. Bu durumda atma etkili HashSet<> null eklemek için herhangi bir girişimde kıracak. HashSet<> sürece yapar null bir madde ile (test olacak) ilgili olağanüstü bir şey.

YENİ EK/EDİT:

Şimdi hata ayıklama denedim. Varsayılan eşitlik karşılaştırıcısı ile doğrulayabilirim HashSet<> Season.Spring null değerleriaynı kova ile bitiyor. Bu çok dikkatli bir şekilde özel dizi üyeleri m_buckets m_slots inceleyerek belirlenebilir. Endeksleri, her zaman, tasarım, bir telafi olduğunu unutmayın.

Yukarıda verdiğim kod, ancak, bunu düzeltmez. Görünüşe göre, HashSet<> hiç değeri null zaman eşitlik karşılaştırıcısı sormaz bile. Bu HashSet<> kaynak kodu:

    // Workaround Comparers that throw ArgumentNullException for GetHashCode(null).
    private int InternalGetHashCode(T item) {
        if (item == null) { 
            return 0;
        } 
        return m_comparer.GetHashCode(item) & Lower31BitMask; 
    }

Bu anlamına geliren azından HashSet<> için bile mümkün null karma değiştirilemez.Bunun yerine, bir çözüm, tüm diğer değerler karma, bu gibi değiştirmek için:

class NewerNullEnumEqComp<T> : EqualityComparer<T?> where T : struct
{
  public override bool Equals(T? x, T? y)
  {
    return Default.Equals(x, y);
  }
  public override int GetHashCode(T? x)
  {
    return x.HasValue ? 1   Default.GetHashCode(x) : /* not seen by HashSet: */ 0;
  }
}

CEVAP
23 Mayıs 2012, ÇARŞAMBA


Karma kodu null döndürülürtutarlıtürü için bir şey olmaz. Karma bir kod için tek şart eşit olarak kabul edilen iki nesne aynı karma kodu paylaşın.

Null 0 veya -1 dönen birini seçin ve geri her zaman sürece çalışacaktır. Belli ki, boş olmayan bir hash kodları null için kullanmak ne olursa olsun geri dönüş olmamalı.

Benzer sorular:

GetHashCode on null fields?

What should GetHashCode return when object's identifier is null?

"Uyarılar" MSDN entry hash kodunu daha ayrıntılı gider. Dokunaklı, belgelere null değerleri herhangi bir kapsama ya da tartışma sağlamazhiç- topluluk içeriği.

Adres sorunu ile numaralama, ya yeniden uygulamak karma kodu döndürür sıfır ekleyin varsayılan "bilinmeyen" numaralama giriş eşdeğer null, ya da sadece kullanmayın null çeteleler.

İlginç, bu arada.

Bu gördüğüm bir diğer sorun genellikle karma kodu olduğunuolamazolmadan null 4 bayt veya daha büyük bir türü temsil ederen az bir çarpışma(tipi boyutu arttıkça daha fazla). Örneğin, bir tamsayı karma kodu full int aralığı kullanır, böylece sadece ınt. Ne değeri bu aralıkta boş seçiyorsunuz? - Hangisi olursa olsun, değeri hash kodu kendisi ile çarpışır.

Kendilerini ve çarpışmalar değil, mutlaka bir sorun vardır, ama orada olduklarını bilmek gerekir. Hash kodları sadece bazı durumlarda kullanılır. MSDN belgeleri de belirtildiği gibi, karma kodları farklı nesneler için farklı değerlere dönüş için garanti edilmez, bu yüzden beklenmemelidir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Ciaran Blumenfeld

    Ciaran Blume

    20 NİSAN 2009
  • curioustravelers

    curioustrave

    12 AĞUSTOS 2006
  • Jonathan D.

    Jonathan D.

    3 Kasım 2006