Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
101 / 42 / 9
Регистрация: 09.12.2012
Сообщений: 596
1

HashSet таки добавляет дубликаты

18.04.2015, 13:31. Показов 3582. Ответов 30
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Если хранить в нем обычные переменные типа стринг или инт, то без проблем. А вот если добавлять туда объекты пользовательского класса, то ни тут то было((
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class People
    {
        public string name { get; set; }
        public int age { get; set; }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            HashSet<People> lydi = new HashSet<People>();
            lydi.Add(new People { name = "Vasya", age = 18 });
            lydi.Add(new People { name = "Vasya", age = 18 });
            lydi.Add(new People { name = "Vasya", age = 18 });
 
            Console.WriteLine("Count = " + lydi.Count); //выводит Count = 3 (((а надо 1
            Console.ReadKey();
        }
    }
Видимо он думает что это разные объекты, а не смотрит по содержимому(( Вопрос как с этим бороться?!
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.04.2015, 13:31
Ответы с готовыми решениями:

Не работает HashSet: добавляются дубликаты
Здравствуйте. Пишу свой класс, для этого мне нужно, чтобы в нем элементы не повторялись. Но HashSet...

Нужно написать программу, которая выводит дубликаты файлов. Дубликаты ищутся по хеш-сумме файла. Код на С#
Привет всем, прошу помощи в освоении C#, разобрался б в рабочем коде, не могу сам написать

Дубликаты в HashSet
Здравствуйте. Подскажите, как сделать так, чтобы коллекция HashSet&lt;Integer&gt; hs = new HashSet&lt;&gt;();...

Обсуждение HashSet, в частности- хранит HashSet объекты отсортированными или нет?
Что-то я не могу понять. Смотрите, мне надо запихать 10000 случайных элементов типа Integer в...

30
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
19.04.2015, 22:14 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от beats Посмотреть сообщение
см. начало темы [...] так и надо
Насколько я понял, надо чтобы проверка проходила по содержимому.
А она по факту не проходит.
Вместо проверки получается утечка памяти.

Цитата Сообщение от beats Посмотреть сообщение
исправил и обновил репо по третьему замечанию
О, динамики пошли!
И сразу же появляется сценарий (довольно распространенный), при котором все вообще полетит к чертовой бабушке:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
struct Foo
{
   public int X { get; set; }
}
class Person : RealHashSet
{
   public string Name { get; set; }
   public Foo Bar { get; set; }
}
 
var a = new Person { Name = "A" };
var b = new Person { Name = "B" };
a.Equals(b); // KABOOM!
Следующая версия — корректная обработка типов-значений.
Потом поговорим о генериках. После них — о СОМ-интеропе.

А потом можно и генерацию хэш-кода разобрать.

Мораль тут в том, что не стоит пытаться реализовать универсальный метод сравнения двух объектов на идентичность. Просто потому, что в приципе не существует универсального метода их сравнивать: в зависимости от модели сравнение может производиться по-разному, не все поля могут в нем участвовать, идентичность объектов может определяться не просто идентичностью полей и т.д.
Хороший пример — DateTimeOffset: 12:00 по Гринвичу и 16:00 по Москве — один и тот же момент времени, хотя значение времени (12:00/16:00) и значение часового пояса (+0/+4) у них различны.

Про производительность сравнения и генерации хэш-кода (особенно хэш-кода!) с использованием рефлексии и динамиков можно даже не говорить.
5
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.04.2015, 02:10 22
Цитата Сообщение от kolorotur Посмотреть сообщение
И сразу же появляется сценарий (довольно распространенный), при котором все вообще полетит к чертовой бабушке:
а что должно было произойти? У меня просто false возвращается.
0
101 / 42 / 9
Регистрация: 09.12.2012
Сообщений: 596
20.04.2015, 09:15  [ТС] 23
Цитата Сообщение от Psilon Посмотреть сообщение
а что должно было произойти? У меня просто false возвращается.
Да он просто пример не тот привел, но понятно в чем дело. Исправил и запушил
Цитата Сообщение от kolorotur Посмотреть сообщение
Про производительность сравнения и генерации хэш-кода (особенно хэш-кода!) с использованием рефлексии и динамиков можно даже не говорить.
Тут спорить не буду, но у меня не столь большие коллекции чтобы это было критично.
Цитата Сообщение от kolorotur Посмотреть сообщение
Хороший пример — DateTimeOffset: 12:00 по Гринвичу и 16:00 по Москве — один и тот же момент времени, хотя значение времени (12:00/16:00) и значение часового пояса (+0/+4) у них различны.
Пример отличный, но не уместный в данном контексте задачи.

Добавлено через 1 минуту
ps если еще косяки найдете по факту то пишите, буду рад
0
Эксперт .NET
5534 / 4298 / 1217
Регистрация: 12.10.2013
Сообщений: 12,332
Записей в блоге: 2
20.04.2015, 09:28 24
Цитата Сообщение от beats Посмотреть сообщение
если еще косяки найдете
Так вы еще от самого первого не избавились. Повторяю еще раз.
1. Необходимость наследования от вашего класса отсекает возможность наследования от еще одного класса (в C# множественное наследование реализации не поддерживается, и обойти это не получится).
2. Исходя из п.1, сразу возникает необходимость прикреплять к проекту еще и файл с вашим классом, что тоже не радует.
3. И как правильно указал ув. kolorotur, не всегда сравнение необходимо производить по всем свойствам объекта. Вполне возможен вариант, что для сравнения на идентичность необходимо выбрать не все поля/свойства, а лишь некоторые, на усмотрение разработчика. Т.о., придется мало того что наследоваться от вашего класса, так еще и исправлять его, что сводит на нет всю его универсальность.
Так что, на мой взгляд, идея не имеет смысла. Гораздо проще переопределить два/три метода в своем классе, если это необходимо.
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
20.04.2015, 11:14 25
Цитата Сообщение от Psilon Посмотреть сообщение
а что должно было произойти?
Исключение вылетает. Вы последнюю версию пробовали, ту, что с динамиками?

Цитата Сообщение от beats Посмотреть сообщение
у меня не столь большие коллекции чтобы это было критично.
Цитата Сообщение от beats Посмотреть сообщение
Пример отличный, но не уместный в данном контексте задачи.
Вот тут становится не понятно: если вы пишете решение под данный контекст задачи, то чем вас не устроило быстрое, простое и эффективное решение, предложенное в самом начале темы?
А если вы пишете универсальный метод сравнения, то причем здесь данный контекст задачи?

Вот уже для простого, казалось бы, сравнения двух объектов к динамикам добавилась XML-сериализация.
Это значит, что решение будет падать на свойствах, которые выбранный метод сериализации не поддерживает. Я вам приведу пример, вы его исправите, внедрив еще какой-нибудь костыль. Я вам покажу пример краша под этот костыль. Вы добавите еще один костыль для костыля. И так до бесконечности. Точнее до того момента, когда у вас не останется инструментов, после чего я напишу объект, сравнение на равенство которого не поддерживается ни одним из используемых вами инструментов.
Для любого "универсального" решения я вам приведу пример, при котором это решение не работает — просто потому, что у любого инструмента есть ограничения по его применению.

По факту же, пытаясь добавить гибкость, вы убиваете в ноль производительность, при этом гибкости не добавляя.
1
101 / 42 / 9
Регистрация: 09.12.2012
Сообщений: 596
20.04.2015, 14:25  [ТС] 26
insite2012, больше похоже на капризы)
kolorotur, у всех универ. решений есть свои минусы, тот же xamarin forms к примеру. Однако я тебя понял) спасибо за ответы, тему можно закрывать.
0
Эксперт .NET
5534 / 4298 / 1217
Регистрация: 12.10.2013
Сообщений: 12,332
Записей в блоге: 2
20.04.2015, 14:48 27
Цитата Сообщение от beats Посмотреть сообщение
больше похоже на капризы)
нет, скорее ваши попытки выставить свое (никуда не годное) решение супер-универсальным больше похоже на каприз непризнанного гения-кодера.
0
101 / 42 / 9
Регистрация: 09.12.2012
Сообщений: 596
20.04.2015, 14:54  [ТС] 28
insite2012, очень смешно, не могу. помойму тема закрыта, или обязательно надо оставить свое последнее сообщение?
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.04.2015, 15:27 29
beats, темы тут не закрывают

kolorotur, я на этом примере вызывал:
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
using System;
using System.Collections.Generic;
 
public class People
{
    public string name { get; set; }
    public int age { get; set; }
 
    public override bool Equals(object obj)
    {
        People q = (People)obj;
        return q != null && q.name == this.name && q.age == this.age;
    }
 
    public override int GetHashCode()
    {
        return this.name.GetHashCode() ^ this.age.GetHashCode();
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        HashSet<People> lydi = new HashSet<People>();
        lydi.Add(new People { age = 18 });
 
        Console.WriteLine("Count = " + lydi.Count); //выводит Count = 3 (((а надо 1
        Console.ReadKey();
    }
}
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
20.04.2015, 15:46 30
Psilon, на битбаките была версия, где значения свойств двух объектов выгружались в динамики и потом сравнивались через оператор !=.

Цитата Сообщение от beats Посмотреть сообщение
я тебя понял)
Поймите правильно — я не придираюсь к вашей реализации, а пытаюсь провести в обход поля, выстланного граблями и объяснить почему по нему не стоит идти напрямую. До вас не одно поколение программистов себе на нем шишки набило — зачем повторять чужие ошибки?
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.04.2015, 16:25 31
kolorotur, а не, не глядя написал. Там была версия с двумя динамиками, да, просто я её не сохранил, а потом студия грохнулась и история изменений вместе с ней, а репозиторий уже удален.

Но возражение с моей ТЗ: насколько это медленно. В принципе у меня была идея сделать универсальный класс, который мог бы генерировать GetHashCode() для любых типов. То есть этакий

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static class ComparerGenerator<T>
{
    private static readonly IEqualityComparer<T> EqualityComparerBackfield = CreateComparer();
 
    public static IEqualityComparer<T> EqualityComparer
    {
        get { return EqualityComparerBackfield; }
    }
 
    private static IEqualityComparer<T> CreateComparer()
    {
        throw new NotImplementedException();
    }
}
для адекватной скорости работы нужно немного повозиться с илом, но думаю, сделать можно.

Добавлено через 2 минуты
Хотя в принципе от EqualityComparer<T> отличаться будет разве что скоростью.
0
20.04.2015, 16:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.04.2015, 16:25
Помогаю со студенческими работами здесь

HashSet. Удалить объект-класс из HashSet
Всем привет! Есть код: HashSet&lt;Human&gt; humanHashSet = new HashSet(); ...

Contains for HashSet
Приветствую! Не находит слово: &quot;Москв&quot; HashSet&lt;string&gt; totalCity = new HashSet&lt;string&gt;(); using...

HashSet
HashSet позволяет внести одинаковые элементы. Я так понимаю и идентичность обосновывается на хешах,...

HashSet
кто может дать полное описание класса HashSet&lt;T&gt;???


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

Или воспользуйтесь поиском по форуму:
31
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru