В этой ситуации, когда один член редактируется так, чтобы он стал равным другому, как правильно заставить HashSet пересчитать хэши и таким образом очистить себя от дубликатов?
Я знал лучше, чем ожидать, что этопроизошло автоматически, поэтому я попытался пересечь HashSet с самим собой, а затем переназначить его вызову конструктора, который ссылается на себя и того же EqualityComparer.Я думал, что последний будет работать, но нет.
Одна вещь, которая действительно удалась, это реконструкция HashSet из его преобразования в некоторый другой тип контейнера, такой как List, а не непосредственно из самого себя.
Класс определения:
public class Test {
public int N;
public override string ToString() { return this.N.ToString(); }
}
public class TestClassEquality: IEqualityComparer<Test> {
public bool Equals(Test x, Test y) { return x.N == y.N; }
public int GetHashCode(Test obj) { return obj.N.GetHashCode(); }
}
Тестовый код:
TestClassEquality eq = new TestClassEquality();
HashSet<Test> hs = new HashSet<Test>(eq);
Test a = new Test { N = 1 }, b = new Test { N = 2 };
hs.Add(a);
hs.Add(b);
b.N = 1;
string fmt = "Count = {0}; Values = {1}";
Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
hs.IntersectWith(hs);
Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
hs = new HashSet<Test>(hs, eq);
Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
hs = new HashSet<Test>(new List<Test>(hs), eq);
Console.WriteLine(fmt, hs.Count, string.Join(",", hs));
Вывод:
"Count: 2; Values: 1,1"
"Count: 2; Values: 1,1"
"Count: 2; Values: 1,1"
"Count: 1; Values: 1"
Основываясь на последнем подходе, я, вероятно, мог бы создать метод расширенияв котором HashSet сбрасывает себя в локальный список, очищает себя, а затем снова заполняет из указанного списка.
Действительно ли это необходимо или есть какой-то более простой способ сделать это?