Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/120: Рейтинг темы: голосов - 120, средняя оценка - 4.69
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923

Сравнение двух объектов

04.12.2018, 18:01. Показов 23612. Ответов 21

Студворк — интернет-сервис помощи студентам
Допустим есть класс квадрат. Он содержит в себе поле "P" -- его периметр к примеру, "S" -- площадь.
C#
1
2
3
4
5
6
7
8
9
10
11
    class Kvadrat
    {
        public int P { get; set; }
        public int S { get; set; }
        public Kvadrat(int P, int S)
        {
            this.P = P;
            this.S = S;
        }
 
    }
В методе Main() я создам два объекта класса Kvadrat: p1 и p2
C#
1
2
            Kvadrat p1 = new Kvadrat(2,4);
            Kvadrat p2 = new Kvadrat(3,5);
Интересует: как сравнить эти два объекта. Я уже гуглил. Очень страшные коды....не может ж быть всё так "сложно"(по крайней мере для новичков).
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.12.2018, 18:01
Ответы с готовыми решениями:

Сравнение двух объектов на эквивалентность
Есть такой код (часть): static void Main(string args) { Point p1 = new Point(); ...

Как правильно сделать сравнение двух объектов по нескольким параметрам?
Доброго времени суток. Столкнулся тут с проблемкой - ничего не могу :( Сравниваю два объекта по его свойствам. Написал вот такой кодик ...

Сравнение двух текстовых переменных и вывод их разницы в виде текста что отличается в двух массивах
Есть две текстовых переменных типа string. Необходимо вывести в третью переменную, разницу этих двух переменных т.е. первая переменная =...

21
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,112
Записей в блоге: 2
04.12.2018, 18:12
Цитата Сообщение от abortion error Посмотреть сообщение
Интересует: как сравнить эти два объекта. Я уже гуглил. Очень страшные коды....не может ж быть всё так "сложно"(по крайней мере для новичков).
А что такое сравнить объекты? Общего метода естественно нет, так это невозможно определить в целом для всех типов.
Конкретно для Вашего случая сравнивайте значения полей P и S, если оба значения совпадают, то объекты равны друг другу. Введите, соответствующий, метод в класс.
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
04.12.2018, 18:56  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
А что такое сравнить объекты?
я это представлял как-то так
C#
1
2
3
4
        public bool sravnenie(object obj)
        {
                return Equals(obj);
        }
Добавлено через 18 минут
Если кому интересно:
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp5
{
    class Kvadrat: IEquatable<Kvadrat>
    {
        public int P { get; set; }
        public int S { get; set; }
        public Kvadrat(int P, int S)
        {
            this.P = P;
            this.S = S;
        }
 
        public override int GetHashCode()
        {
            return P ^ S;
        }
        public bool Equals(Kvadrat other)
        {
            if (other == null)
                return false;
            if (object.ReferenceEquals(this, other))
                return true;
            if (this.GetType() != other.GetType())
                return false;
            if (string.Compare(Convert.ToString(this.P), Convert.ToString(other.P), this.P.Equals(other.P)) == 0 && this.S.Equals(other.S))
                return true;
            else
                return false;
        }
 
 
    }
    class Program
    {
        static void Main(string[] args)
        {
            Kvadrat p1 = new Kvadrat(4,4);
            Kvadrat p2 = new Kvadrat(4,4);
            Console.WriteLine(p1.Equals(p2));
            Console.ReadLine();
        }
    }
}
0
 Аватар для PoPsa85
814 / 561 / 240
Регистрация: 01.07.2018
Сообщений: 1,818
04.12.2018, 18:57
abortion error, Создайте еще один объект Kvadrat p3 = new Kvadrat(2,4); и сравните его с p1 через
p3.Equals(p1)
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,112
Записей в блоге: 2
04.12.2018, 19:10
Лучший ответ Сообщение было отмечено abortion error как решение

Решение

Цитата Сообщение от abortion error Посмотреть сообщение
я это представлял как-то так
Метод Equals должен возвращать разные значения для разных объектов, даже если у этих объектов идентичные данные. Иначе можете позже столкнуться с непонятными багами. Тоже самое касается метода GetHashCode.
Для сравнения по значениям полей создайте метод с другим названием.
Допустим такой вариант
C#
1
2
3
4
public bool Different (Kvadrat kvadrat) =>
       kvadrat == null 
       ? true
       : (this.P != kvadrat.P || this.S != kvadrat.S);
Возвращает true если объекты разные
1
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
04.12.2018, 19:11  [ТС]
false, собственно как мне и нужно. Работает правильно, но что если нужно проверить не два элемента, а три, допустим это треугольник:
C#
1
2
3
4
        public override int GetHashCode()
        {
            return a ^ b ^c;
        }
Как будет выглядеть эта строка?
C#
1
if (string.Compare(Convert.ToString(this.a), Convert.ToString(other.a), this.a.Equals(other.a)) == 0 && this.b.Equals(other.b))
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
04.12.2018, 19:13
Цитата Сообщение от abortion error Посмотреть сообщение
Интересует: как сравнить эти два объекта.
Самое простое и самое подходящее для данного случая, так как каждый объект - совокупность двух чисел:
сделать эти объекты структурами и проверять их побитовое равенство:
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
using System;
 
namespace Question2364434
{
    struct Kvadrat
    {
        public int P { get; set; }
        public int S { get; set; }
        public Kvadrat(int P, int S)
        {
            this.P = P;
            this.S = S;
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Kvadrat p1 = new Kvadrat(2, 4);
            Kvadrat p2 = new Kvadrat(3, 5);
            Kvadrat p3 = new Kvadrat(2, 4);
            Console.WriteLine(Object.Equals(p1, p2));
            Console.WriteLine(Object.Equals(p1, p3));
            Console.ReadKey();
        }
    }
}
А что больше или меньше - вопрос уже другой. Периметр практически не коррелирует с площадью.
Там уже надо по "больше-меньше" отдельно сравнивать по площади и отдельно по периметру.
2
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
04.12.2018, 19:17  [ТС]
Коротко, работает, красиво выглядит, практичней. Спасибо

Добавлено через 1 минуту
Цитата Сообщение от Элд Хасп Посмотреть сообщение
public bool Different (Kvadrat kvadrat) =>
* * * *kvadrat == null
* * * *? true
* * * *: (this.P != kvadrat.P || this.S != kvadrat.S);
...
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
04.12.2018, 20:41
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Метод Equals должен возвращать разные значения для разных объектов, даже если у этих объектов идентичные данные. Иначе можете позже столкнуться с непонятными багами. Тоже самое касается метода GetHashCode.
Элд Хасп, это кто вам такое сказал?

Добавлено через 5 минут
Дока:
If you implement IEquatable<T>, you should also override the base class implementations of Equals(Object) and GetHashCode() so that their behavior is consistent with that of the Equals(T) method.
В том то и дело, что если мы определяем семантику равенства двух объектов, то мы соответственно, отходим от сравнения по ссылке.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,112
Записей в блоге: 2
04.12.2018, 20:45
Цитата Сообщение от IamRain Посмотреть сообщение
Элд Хасп, это кто вам такое сказал?
Сам столкнулся с этим в WPF. Можете прочитать ссылка на форум
Проблема была именно в переопределённом методе Equals
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
04.12.2018, 21:32
IamRain, Элд Хасп,
в данной теме мы видим типичный ValueObject. Побитового равенства полей для эквивалентности там за глаза хватает.
Городить там надо только для компаратора, и то не надо.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
04.12.2018, 21:57
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Сам столкнулся с этим в WPF.
В WPF, насколько я помню, чтобы контрол узнал об изменении того или иного свойства, то реализуется INotifyPropertyChanged (так, либо косвенно, через какой-либо MVVM фреймворк).
Привязка к контролам коллекций - это ObservableCollection (добавление, удаление).

Элд Хасп, касательно вашей темы в этом кабаке на sql.ru - а зачем там нужно свойство CurrentClient? -
можно ведь просто SelectedClient пробрасывать. И проблем из за разных ссылок не будет. Видимо, при передаче на редактирование из грида идет по ссылке.

Добавлено через 11 минут
amr-now,
Не знал, что у ValueType Object.Equals переопределен:

The ValueType.Equals(Object) method overrides Object.Equals(Object) and provides the default implementation of value equality for all value types in the .NET Framework.

If none of the fields of the current instance and obj are reference types, the Equals method performs a byte-by-byte comparison of the two objects in memory.
Но:
Particularly if your value type contains fields that are reference types, you should override the Equals(Object) method
0
Эксперт JS
6496 / 3907 / 2006
Регистрация: 14.06.2018
Сообщений: 6,781
04.12.2018, 22:00
IamRain, а тут как раз именно пара чисел.

Цитата Сообщение от IamRain Посмотреть сообщение
Не знал,
Одновременно мы сейчас на соседней ветке по Javascript тоже пару мистических тайн раскрыли ))
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
04.12.2018, 22:03
Но блин, все-таки потратить пару минут на реализацию и Equatable и можно не бояться за поведение в Windows Runtime, как никак, это все таки более наглядно (и поэтому, более правильно).
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,112
Записей в блоге: 2
04.12.2018, 22:07
Цитата Сообщение от IamRain Посмотреть сообщение
В WPF, насколько я помню, чтобы контрол узнал об изменении того или иного свойства, то реализуется INotifyPropertyChanged (так, либо косвенно, через какой-либо MVVM фреймворк).
Привязка к контролам коллекций - это ObservableCollection (добавление, удаление).
Я это всё знаю.
Цитата Сообщение от IamRain Посмотреть сообщение
касательно вашей темы в этом кабаке на sql.ru - а зачем там нужно свойство CurrentClient? -
можно ведь просто SelectedClient пробрасывать. И проблем из за разных ссылок не будет. Видимо, при передаче на редактирование из грида идет по ссылке.
Такая реализация нужна была для создания копии перед редактированием. И из-за того что копия и оригинал были эквивалентны (Класс состоит всего из одного string значения) работа привязок рушилась. При этом в коде C# всё определялось нормально.
Что я хочу сказать, в процессе разбирательства с этой проблемой, выяснилось, что порой FW в каких-то классах, методах для нахождения объектов использует функции Equals и GetHashCode. И если эти функции возвращают одинаковое значение для разных объектов, то можно нарваться на непредсказуемую работу приложения.

Добавлено через 2 минуты
Так, конечно, не должно быть. Но такое есть. Наверное это баг. Но как выяснилось баг довольно частый. Так как при моём обращении о помощи, первый же ответ был - исправьте Equals и GetHashCode. После исправления стало всё работать нормально. А для сравнения объектов создал метод с другим именем.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
04.12.2018, 22:18
Цитата Сообщение от Элд Хасп Посмотреть сообщение
порой FW в каких-то классах, методах для нахождения объектов использует функции Equals и GetHashCode
Именно базового Object - сравнение по ссылке - нюанс работы в WPF. Это надо просто знать, видимо.

Если например, как контрагрумент, взять какое-нибудь сложное веб-приложение, которое с одной стороны имеет БД c людьми
(Person), и с другой, какое-нибудь удаленное ElasticSearch хранилище, и нам время от времени надо их как-то сихронизировать.
То искать надо будет людей по пасспорту (или ИНН), а не по ссылке, иначе ничего не найдете, даже если данные будут совпадать.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,112
Записей в блоге: 2
04.12.2018, 23:01
Цитата Сообщение от IamRain Посмотреть сообщение
Это надо просто знать, видимо
Да, надо знать.... Но однажды обжёгшийся, дуешь и на холодную воду..
Даже в данном случае. Сейчас пока просто класс с int полями. Потом дополнит к его, начнёт View делать на WPF. И чёрт его знает где это стрельнет потом. И будет потом искать..... то, что полгода назад не так переопределил метод сравнения.

Цитата Сообщение от IamRain Посмотреть сообщение
Если например, как контрагрумент, взять какое-нибудь сложное веб-приложение, которое с одной стороны имеет БД c людьми
(Person), и с другой, какое-нибудь удаленное ElasticSearch хранилище, и нам время от времени надо их как-то сихронизировать.
То искать надо будет людей по пасспорту (или ИНН), а не по ссылке, иначе ничего не найдете, даже если данные будут совпадать.
Я же не говорю, что не надо сравнивать. У меня тоже там именно из-за необходимости сравнения я и переопределил Equals. Просто раз такое переопределение иногда вызывает проблемы, можно же методу сравнения дать иное имя. Чем это мешает? Зато гарантирует, что не будет ни каких проблем.
0
1524 / 515 / 126
Регистрация: 09.01.2018
Сообщений: 1,614
04.12.2018, 23:11
Цитата Сообщение от abortion error Посмотреть сообщение
Интересует: как сравнить эти два объекта.
Сравнивайте по значениям:

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
53
54
55
    class Program
    {
        static void Main(string[] args)
        {
            Square sq_0 = new Square(40, 100);
            Square sq_1 = new Square(40, 100);
 
            Console.WriteLine(sq_0.Equals(sq_1)); //true
            Console.WriteLine(sq_0.GetHashCode()); //440
            Console.WriteLine(sq_1.GetHashCode()); //440
 
            Console.WriteLine(ReferenceEquals(sq_0, sq_1)); //false
            Console.WriteLine();
 
            sq_1 = new Square(50, 150);
 
            Console.WriteLine(sq_0.Equals(sq_1)); //false
            Console.WriteLine(sq_0.GetHashCode()); //440
            Console.WriteLine(sq_1.GetHashCode()); //618
 
            Console.WriteLine(ReferenceEquals(sq_0, sq_1)); //false
 
            Console.ReadKey();
        }
    }
 
    class Square
    {
        public int P { get; set; }
        public int S { get; set; }
 
        public Square(int p, int s)
        {
            P = p;
            S = s;
        }
 
        public override bool Equals(Object obj)
        {
            if ((obj == null) || !this.GetType().Equals(obj.GetType()))
            {
                return false;
            }
            else
            {
                Square sq = (Square)obj;
                return (P == sq.P) && (S == sq.S);
            }
        }
 
        public override int GetHashCode()
        {
            return S << 2 ^ P;
        }
    }
А вот так не пойдет
Цитата Сообщение от abortion error Посмотреть сообщение
C#
1
2
3
4
        public override int GetHashCode()
        {
             return P ^ S;
        }
Получите одинаковые значения при например
Code
1
2
3
P = 40, S = 100 
и
P = 100, S = 40
В теории такого быть не может, но вы же просто задаете значения в конструкторе.
0
 Аватар для IamRain
4694 / 2702 / 734
Регистрация: 02.08.2011
Сообщений: 7,233
04.12.2018, 23:17
Цитата Сообщение от escoult Посмотреть сообщение
Получите одинаковые значения при например
Это нормально, для этого GetHashCode и придумали, что-то вроде того - если данных много, то иерархический подход к поиску упрощает/ускоряет этот поиск. Возьмите к примеру работу почты, либо те же индексы в базе.
А ваше требование относится только к Equals.
0
1524 / 515 / 126
Регистрация: 09.01.2018
Сообщений: 1,614
05.12.2018, 00:07
Цитата Сообщение от IamRain Посмотреть сообщение
Это нормально, для этого GetHashCode и придумали,
Не изучал этот вопрос подробно. Насколько я понимаю, такая коллизия повлечет за собой ошибки в работе компаратора. Два объекта будет считаться равными, хотя на самом деле они не равны.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.12.2018, 00:07
Помогаю со студенческими работами здесь

Сравнение объектов в C#
Привет. Запутался с методами сравнения объектов (ссылочных, значимых и отдельно строк) ==, Equals, ReferenceEquals. Что для чего...

Сравнение объектов
Как проверить равенство всех полей экземпляров класса без кучи условий в if?

Сравнение нескольких объектов
Что скажете про такую лабуду? string month = &quot;July&quot;; if (month == &quot;June&quot;.Or(&quot;July&quot;).Or(&quot;August&quot;)) Console.WriteLine(&quot;Summer...

Сравнение объектов по дате
Доброго времени суток! Никак до конца не могу разобраться с тем, как работает System.Collections.Generic.IComparer&lt;T&gt;. У меня есть...

Сравнение объектов одного типа
Здравствуйте, господа. Ситуация следующая: есть 2 объекта одного типа, абсолютно одинаковые по свойствам и их значениям, но разными...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при создании или изменении элементов справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи электронной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru