Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
nexen
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
#1

Dictionary с адресами классов в качестве ключей - C#

24.07.2013, 19:09. Просмотров 758. Ответов 14
Метки нет (Все метки)

Предположим есть такой код:
C#
1
MyClass x, y;
У класса MyClass есть конструктор по умолчанию, так что x и y равны. Я хочу, чтобы выполнялось условие:
C#
1
2
3
Dictionary <MyClass, int> m;
...
if (m[x] != m[y])..
То есть, я хочу, чтобы в качестве включа словаря использовались ссылки на объекты, и условие выглядело фактически m[0x183AF9] != m[0x183AFF]
http://www.cyberforum.ru/csharp-beginners/thread2008808.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.07.2013, 19:09
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Dictionary с адресами классов в качестве ключей (C#):

Извлечь массив значений из Dictionary с помощью массива ключей
Как можно извлечь из экземпляра Dictionary массив значений при помощи...

Нужно пройтись по списку ключей Dictionary и записать их через запятую
Нужно как то упростить мой быдлокод) int i = 0; string homesName =...

Как получить строковое представление ключей и значений из коллекции Dictionary
Как получить строковое представление значений ключе я значений из коллекции...

Массив в качестве значения в dictionary
Здравствуйте, господа программисты. прошу вашей помощи. Имею следующую...

Задачи на наследование классов, в которых данные описаны в качестве свойств
Создать класс Money для работы с денежными суммами в котором для рублей и...

14
turbanoff
Эксперт Java
4008 / 3743 / 739
Регистрация: 18.05.2010
Сообщений: 9,323
Записей в блоге: 11
Завершенные тесты: 1
24.07.2013, 20:43 #2
Цитата Сообщение от nexen Посмотреть сообщение
У класса MyClass есть конструктор по умолчанию, так что x и y равны.
Странное утверждение, учитывая что вы не вызываете конструктор, и то что конструктор всегда создает новый объект.
0
nexen
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
24.07.2013, 20:46  [ТС] #3
turbanoff, ну это я уже от С++ взял случайно Представьте, что там x = new MyClass(), y = new MyClass()
0
turbanoff
Эксперт Java
4008 / 3743 / 739
Регистрация: 18.05.2010
Сообщений: 9,323
Записей в блоге: 11
Завершенные тесты: 1
24.07.2013, 20:50 #4
У конструктора Dictionary есть параметр, который позволяет использовать свой способ сравнения объектов.
Можно его реализовать, например, так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
class ReferenceEqualityComparer<T> : IEqualityComparer<T>
{
    public bool Equals(T x, T y)
    {
        return object.ReferenceEquals(x, y);
    }
 
    public int GetHashCode(T obj)
    {
        return RuntimeHelpers.GetHashCode(obj);
    }
}
C#
1
2
var eqComparer = new ReferenceEqualityComparer<MyClass>();
Dictionary<MyClass, int> m = new Dictionary<MyClass, int>(eqComparer);
Теперь, какие бы объекты вы не ложили в словарь, они всегда будут сравниваться по ссылкам.
0
nexen
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
24.07.2013, 21:44  [ТС] #5
turbanoff, а зачем перегружать метод с получением хэша?
0
Psilon
Master of Orion
Эксперт .NET
5981 / 4834 / 901
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
24.07.2013, 21:49 #6
nexen, потому что словарь сначала проверяет равенство хеша, если они не совпадают - то проверять дальше смысла нету - объекты разные. Если же совпадают, тогда начинается более глубокая проверка. Во-первых хэш высчитывается один раз, во-вторых он затем складывается в скрытое поле класса, откуда получается при последующих запросах без новых вычислений. Таким образом достигается неплохой буст производительности.
1
turbanoff
Эксперт Java
4008 / 3743 / 739
Регистрация: 18.05.2010
Сообщений: 9,323
Записей в блоге: 11
Завершенные тесты: 1
24.07.2013, 21:58 #7
Цитата Сообщение от Psilon Посмотреть сообщение
Во-первых хэш высчитывается один раз, во-вторых он затем складывается в скрытое поле класса
Даже сторонний хэш, как в моем примере?

Добавлено через 1 минуту
Цитата Сообщение от nexen Посмотреть сообщение
а зачем перегружать метод с получением хэша?
Этого требует интерфейс IEqualityComparer<T>
1
Psilon
Master of Orion
Эксперт .NET
5981 / 4834 / 901
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
24.07.2013, 22:03 #8
turbanoff, в данном случае я ответил на следующий по логике вопрос, зачем обязательно его переопределять.

Поищу пруфы пока, если нужно.

Добавлено через 2 минуты
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
private void Insert(TKey key, TValue value, bool add)
    {
      if ((object) key == null)
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
      if (this.buckets == null)
        this.Initialize(0);
      int num1 = this.comparer.GetHashCode(key) & int.MaxValue;
      int index1 = num1 % this.buckets.Length;
      int num2 = 0;
      for (int index2 = this.buckets[index1]; index2 >= 0; index2 = this.entries[index2].next)
      {
        if (this.entries[index2].hashCode == num1 && this.comparer.Equals(this.entries[index2].key, key))
        {
          if (add)
            ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
          this.entries[index2].value = value;
          ++this.version;
          return;
        }
        else
          ++num2;
      }
      int index3;
      if (this.freeCount > 0)
      {
        index3 = this.freeList;
        this.freeList = this.entries[index3].next;
        --this.freeCount;
      }
      else
      {
        if (this.count == this.entries.Length)
        {
          this.Resize();
          index1 = num1 % this.buckets.Length;
        }
        index3 = this.count;
        ++this.count;
      }
      this.entries[index3].hashCode = num1;
      this.entries[index3].next = this.buckets[index1];
      this.entries[index3].key = key;
      this.entries[index3].value = value;
      this.buckets[index1] = index3;
      ++this.version;
      if (num2 <= 100 || !HashHelpers.IsWellKnownEqualityComparer((object) this.comparer))
        return;
      this.comparer = (IEqualityComparer<TKey>) HashHelpers.GetRandomizedEqualityComparer((object) this.comparer);
      this.Resize(this.entries.Length, true);
    }
1
turbanoff
Эксперт Java
4008 / 3743 / 739
Регистрация: 18.05.2010
Сообщений: 9,323
Записей в блоге: 11
Завершенные тесты: 1
24.07.2013, 22:03 #9
Цитата Сообщение от Psilon Посмотреть сообщение
Поищу пруфы пока, если нужно.
Да не нужно. Я твердо знаю, что в скрытых полях классах не сохранить все хэши посчитанные сторонними IEqualityComparer-ами.
1
Psilon
Master of Orion
Эксперт .NET
5981 / 4834 / 901
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
24.07.2013, 22:05 #10
turbanoff, в поле естественно сохраняется только посчитанное самим объектом GetHashCode, а не сторонним, но в остальном механизм тот же.
1
turbanoff
Эксперт Java
4008 / 3743 / 739
Регистрация: 18.05.2010
Сообщений: 9,323
Записей в блоге: 11
Завершенные тесты: 1
24.07.2013, 22:06 #11
Цитата Сообщение от Psilon Посмотреть сообщение
в остальном механизм тот же.
В смысле тот-же? Считается один раз? Или сохраняется в поле класса?
1
Psilon
Master of Orion
Эксперт .NET
5981 / 4834 / 901
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
24.07.2013, 22:07 #12
turbanoff, в смысле используется в качестве первого приближения равенства объектов.
1
nexen
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
25.07.2013, 07:46  [ТС] #13
А разве нормально хэш подсчитается от кастомного класса?

И всё же зачем мне кэш, если у меня сравниваются адреса? То же самое, что вместое сравнения int1 и int2 произвести сравниение: Equal(Hash(int1), Hash(int2)); - два раза считается ненужный хэш, ведь он так же равен типу int
0
turbanoff
Эксперт Java
4008 / 3743 / 739
Регистрация: 18.05.2010
Сообщений: 9,323
Записей в блоге: 11
Завершенные тесты: 1
25.07.2013, 08:01 #14
nexen, Прочитайте описание RuntimeHelpers.GetHashCode
RuntimeHelpers.GetHashCode полезен в скриптах, в которых важна идентификация объекта. Для двух строк с идентичным содержимым метод RuntimeHelpers.GetHashCode вернет различные значения, так как они являются разными строковыми объектами, хотя и с одинаковым содержимым.
1
MrCold
859 / 757 / 174
Регистрация: 11.01.2012
Сообщений: 1,942
25.07.2013, 09:25 #15
Цитата Сообщение от nexen Посмотреть сообщение
если у меня сравниваются адреса?
Какие могут быть адреса ? Сборка мусора и уплотнение памяти же ...
0
25.07.2013, 09:25
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.07.2013, 09:25
Привет! Вот еще темы с решениями:

Задачи на использование классов и объектов, в которых данные описаны в качестве свойств
Круг на плоскости имеет координаты центра x0,y0 - вещественные свойства. Радиус...

Проинициализировать значениями dictionary вложенный в dictionary
Народ, помогите, как проинициализировать значениями такую конструкцию: ...

Генерация и проверка на работоспособность ключей активации (регистрационных ключей)
Помогите придумать как можно осуществить сие деяние. Суть заключается в чем,...

Как привести (состыковать) разные типы из разных классов (исп в качестве выходного параметра в методе)
Вопрос состоит в том как максимально просто заставить работать такой...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru