powered by simpleCommunicator - 2.0.27     © 2024 Programmizd 02
Map
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / ConcurrentDictionary co struct в качестве ключа.
8 сообщений из 8, страница 1 из 1
ConcurrentDictionary co struct в качестве ключа.
    #40082326
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Структура состоит из двух текстовых полей, если одно из них null, то такой ключ не работает, можно набить в Dictionary сколько угодно ключей с одинаковым значением второго поля, и, соответственно, такой ключ не ищется. IEqualityComparer<T> использую, не помогает. Если оба поля не null, проблем нет.

Можно ли заставить коллекцию понимать такие ключи с null'ами?
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40082488
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy
Если оба поля не null, проблем нет.

Да и если какое-нибудь null (и даже оба null) проблем нет:
Код: 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.
51.
52.
class Program
{
  static void Main()
  {
    var cd = new ConcurrentDictionary<Foo, int>(new FooComparer());
    foreach (var f in new[]
    {
      new Foo(),
      new Foo(),
      new Foo{Bar = "A"},
      new Foo{Bar = "A"},
      new Foo{Zot = "B"},
      new Foo{Zot = "B"},
      new Foo{Bar="A", Zot = "B"},
      new Foo{Bar="A", Zot = "B"},
      new Foo{Bar="A", Zot = "C"}
    })
      Console.WriteLine("{0} : {1}", f, cd.TryAdd(f, 0));
  }
}

public struct Foo
{
  public string Bar;
  public string Zot;
  public override string ToString()
  {
    return $"Bar={(Bar ?? "null")}, Zot={(Zot ?? "null")}";
  }
}

public class FooComparer : IEqualityComparer<Foo>
{
  public bool Equals(Foo x, Foo y)
  {
    var f1 = (x.Bar == null && y.Bar == null) ||
         (x.Bar != null && y.Bar!=null && x.Bar.Equals(y.Bar, StringComparison.Ordinal));
    var f2 = (x.Zot == null && y.Zot == null) ||
         (x.Zot != null && y.Zot!=null && x.Zot.Equals(y.Zot, StringComparison.Ordinal));
    return f1 && f2;
  }

  public int GetHashCode(Foo foo)
  {
    var hashes = new[]
    {
      foo.Bar?.GetHashCode() ?? 0,
      foo.Zot?.GetHashCode() ?? 0
    };
    return hashes.Aggregate(hashes.Length, (current, t) => unchecked(current * 314159 + t));
  }
}


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Bar=null, Zot=null : True
Bar=null, Zot=null : False
Bar=A, Zot=null : True
Bar=A, Zot=null : False
Bar=null, Zot=B : True
Bar=null, Zot=B : False
Bar=A, Zot=B : True
Bar=A, Zot=B : False
Bar=A, Zot=C : True
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40085729
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А почему 314159?
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40085768
Фотография pation
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy
А почему 314159?

оч. сложное вычисление хеша.
На мой взгляд подошлобы такое:

Код: c#
1.
return $"{foo.Bar}_{foo.Zot}".GetHashCode();
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40085863
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
от структуры в 2 текстовых поля толку, как с козла молока.
строки, это ссылочный тип, а не тип значения. по сути у тебя структура это 2 адреса на 2 строки, которые не гарантируют того, что при = строках, адреса будет одинаковые.
просто создай класс и переопредели в нем хеш функцию и оператор сравнения

если речь про core.net, то советую использовать
https://docs.microsoft.com/ru-ru/dotnet/api/system.hashcode.combine?view=net-5.0
и не городить квадратные колёса на велосипед
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40085865
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и еще, в качестве типа которые сравниваются, очень удобно использовать анонимные типы и tuple , сравнение в них уже переопределено и будет работать как надо
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40087812
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,
https://github.com/microsoft/referencesource/blob/master/mscorlib/system/valuetype.cs

/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex. We look
** for the first non-static field and get it's hashcode. If the type has no
** non-static fields, we return the hashcode of the type. We can't take the
** hashcode of a static member because if that member is of the same type as
** the original type, we'll end up in an infinite loop.
**Returns: The hashcode for the type.
**Arguments: None.
**Exceptions: None.
==============================================================================*/
...
Рейтинг: 0 / 0
ConcurrentDictionary co struct в качестве ключа.
    #40087866
fkfka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Перегрузи нормально GetHashCode. Долго объяснять зачем, просто перегрузи и все.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / ConcurrentDictionary co struct в качестве ключа.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали тему (0):
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]