2015-09-27 14 views
5

Anonim sınıf için GetHashCode() uygulama oluştururken, Roslyn özellik adlarına dayanarak ilk karma değerini hesaplar. Örneğin, sınıf Adsız sınıf için GetHashCode() uygulamasında başlangıç ​​karma değeri neden özellik adlarına bağlıdır?

var x = new { Int = 42, Text = "42" }; 

aşağıdaki GetHashCode() yöntemine sahip olacak

için oluşturulan:

public override in GetHashCode() 
{ 
    int hash = 339055328; 
    hash = hash * -1521134295 + EqualityComparer<int>.Default.GetHashCode(Int); 
    hash = hash * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Text); 
    return hash; 
} 

Ama biz özellik adları, başlangıç ​​değeri değiştiğinde değiştirirseniz:

var x = new { Int2 = 42, Text2 = "42" }; 

public override in GetHashCode() 
{ 
    int hash = 605502342; 
    hash = hash * -1521134295 + EqualityComparer<int>.Default.GetHashCode(Int2); 
    hash = hash * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Text2); 
    return hash; 
} 

Bu davranışın arkasındaki sebep nedir? Sadece büyük [asal] numarayı seçmek ve tüm anonim sınıflar için kullanmakla ilgili bir problem var mı?

+0

Farklı türlerde nesneler "daha" farklı olacak şekilde farklı sabitler kullanırsanız, bana göre daha yararlı görünüyor. – usr

cevap

6

Sadece büyük bir [asal] numarası almak ve tüm anonim sınıflar için kullanmakla ilgili bir sorun var mı?

Bunu yapmakta yanlış olan hiçbir şey yok, yalnızca daha az verimli bir değer üretme eğilimindedir.

GetHashCode uygulamasının amacı, eşit olmayan değerler için farklı sonuçlar döndürmektir. Bu, değerler karma tabanlı koleksiyonlarda kullanıldığında (Dictionary<TKey, TValue> gibi) çarpışma şansını azaltır.

Anonim değerler, farklı türleri temsil ediyorlarsa, başka bir anonim değere eşit olamazlar. isimsiz değer türü özelliklerini şekli ile tanımlanır: özelliklerinin

  • Adı
  • özelliklerinin
  • tipi herhangi bir farklılık özelliklerini

iki anonim değerleri

  • Sayısı Bu özellikler farklı türleri temsil eder ve dolayısıyla asla eşit değerler olamaz.

    Bunun doğru olduğu göz önüne alındığında, derleyicinin farklı türler için farklı değerler döndürme eğilimi olan GetHashCode uygulamalarını oluşturması mantıklıdır. Bu nedenle, başlangıç ​​karma değerini hesaplarken the compiler özellik adlarını içerir.

  • +0

    Anladım.Herhangi bir nedenden dolayı 'HashSet 'içine farklı türdeki örnekleri koyarsanız, sabit başlangıç ​​değerine sahip karma kodlar yüzünüzde patlayabilir. – HellBrick

    +0

    Ancak, farklı türdeki nesneler için karma değerleri ayırt etmek genellikle iyi bir fikirse, varsayılan olarak yapıldığı zaman neden tek örnek olarak amony sınıflar olur? Henüz BCL'de bunun tek bir örneğini bulamadım. Örneğin, Int64, TimeSpan ve DateTime temel olarak uygulamayı ve 0L.GetHashCode() '==' TimeSpan.Zero.GetHashCode() '==' varsayılan (DateTime) .GetHashCode() 'paylaşır. – HellBrick

    +0

    @ HellBrick farklılaşmanın sadece değerlerin aynı karma yapıya eklenmesi olası olduğunda ilginçtir. Bunu yapmak için farklı türlerin anonim değerleri aslında nadir değildir. Ancak, muhtemelen, bir karma yapının, hem "DateTime" hem de "TimeSpan" değerlerinin anahtar olarak olacağı oldukça nadirdir. – JaredPar

    4

    Roslyn ekibinden biri adım atmadıkça, sadece spekülasyon yapabiliriz. Ben de aynı şekilde yapardım. Her bir anonim tür için farklı bir tohum kullanmak, karma kodlarda daha fazla rastlantısallığa sahip olmanın yararlı bir yolu gibi görünüyor. Örneğin, true olması için new { a = 1 }.GetHashCode() != new { b = 1 }.GetHashCode() neden olur.

    Ayrıca karma kod hesaplamalarının parçalanmasına neden olan herhangi bir bozuk tohum olup olmadığını merak ediyorum. Ben öyle düşünmüyorum. 0 numaralı tohum bile çalışırdı.

    Roslyn kaynak kodu AnonymousTypeGetHashCodeMethodSymbol'da bulunabilir. Başlangıç ​​karma kod değeri, anonim türün isimlerinin bir özetine dayanır.

    İlgili konular