2013-03-14 2 views
1

Я ищу объекты кэша, уникальность которых определяется комбинацией всех свойств внутри этого объекта. Объект У меня есть что-то вроде этого:Как кэшировать объект с несколькими свойствами

public double A { get; set; } 
    public double B { get; set; } 
    public short C { get; set; } 
    public bool D { get; set; } 
    public double E { get; set; } 
    public double F { get; set; } 
    public double G { get; set; } 
    public double H { get; set; } 
    public double J { get; set; } 
    public double K { get; set; } 
    public double[] L { get; set; } 
    public double[] M { get; set; } 

Я мог бы переписать GetHashCode и сделать что-то вроде return A^B^C etc... Однако, я обеспокоен тем, что у меня будет много столкновений.

Что было бы лучшим способом кэшировать такой объект?

+0

Лучший способ ... состоит в том, чтобы перезаписать GetHashCode и сделать что-то вроде A^B^C ... Если вы протестируете и появились столкновения, то выясните, как настроить формулу для ваших нужд. Не изобретайте велосипед –

+0

Поскольку у ваших свойств есть публичные сеттеры, нет гарантии, что данные не будут меняться между последовательными вызовами '.GetHashCode'. Если это состояние изменится, это приведет к полностью нарушенному поведению для всего, что зависит от хеш-кодов, таких как словари. –

+0

Вы имеете право на беспокойство; если ваши свойства имеют тенденцию «кластеризовать», тогда возможно, что xoring завершит очистку множества бит. –

ответ

4

Вы можете использовать этот GetHashCode:

public override int GetHashCode() 
{ 
    int hash = 23; 
    unchecked 
    { 
     hash *= 17 + A.GetHashCode(); 
     hash *= 17 + B.GetHashCode(); 
     hash *= 17 + C.GetHashCode(); 
     // the same applies with the rest of your properties ... 
     // collections must be treated differently: 
     if(L != null) 
     { 
      hash *= 17 + L.Length; 
      foreach(var d in L) 
       hash *= 17 + d.GetHashCode(); 
     } 
     if (M != null) 
     { 
      hash *= 17 + M.Length; 
      foreach (var d in M) 
       hash *= 17 + d.GetHashCode(); 
     }   
    } 
    return hash; 
} 

Это создает различные hashcodes, когда различные свойства имеют одинаковое значение. Если бы я опускал простые умножители, это не имело бы значения, если A==A или A==B. Простые числа используются для уменьшения вероятности ложных столкновений.

Он также принимает во внимание массивы и их значения + порядок.

Это «должен прочитать» по этой теме: E. Lippert, Guidelines and rules for GetHashCode

+0

Какова цель 17 и 23? – TJF

+0

@ ThomasJ.Frey: Посмотрите на этот ответ, который задает этот вопрос: http://stackoverflow.com/a/3613382/284240 Вкратце: простые символы помогут вам избежать получения одинакового значения хэша для разных входных параметров. –

+1

Они также генерируют разные хэш-коды, когда разные свойства имеют одинаковое значение. Если бы я опустил множитель 23, это не имело бы значения, если 'A' ==' A' или 'A' ==' B'. –

0

Простой (Altough, вероятно, не является оптимальным) решением может быть:

  1. Сформировать строковое представление вашего класса. Если у вас были только эскаларные свойства, вы могли бы сделать что-то вроде string.Format("{0}-{1}-{2}", A, B, C); поскольку у вас есть массивы, лучше использовать StringBuilder и составить строку в цикле.

  2. Invoke GetHashCode на сгенерированной строке.

+0

Я не думаю, что это было бы намного проще, если бы правильно вычислил хэш-код. Особенно, если для этого был создан вспомогательный метод. – svick

Смежные вопросы