Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/13: Рейтинг темы: голосов - 13, средняя оценка - 5.00
2 / 2 / 1
Регистрация: 22.09.2014
Сообщений: 132

Метод Equals для значимых типов

30.12.2015, 21:36. Показов 2649. Ответов 10

Студворк — интернет-сервис помощи студентам
Опять Рихтер, наверное многим на форуме это непонятно, но спустя год КОДЕРСТВА, я понял что пора становится инженером, то есть программистом (вернее это показали результаты собеседования на мое первое место работы).
и теперь приходится перечитывать книги с глубоким пониманием и разбором не только C# кода, но и IL-кода.
ВОПРОС по методу Equals.
Рихтер пишет о том, что для значимых типов перегружен этот метод Equals который не сравнивает объекты. а сравнивает типы (если я правильно понял)
Добавив к коду Рихтера класс
C#
1
2
3
4
 struct SomeVal2     // Значимый тип (поскольку 'struct')
    {
        public Int32 x;
    }
экземпляр класса
C#
1
SomeVal2 v2 = new SomeVal2();// Размещается в стеке
и метод сравнения двух значимых типов
C#
1
Console.WriteLine(v1.Equals(v2));
Не могу понять почему выдает FALSE.
Поясните, что не так понял.


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
    class SomeRef // Ссылочный тип (поскольку 'class')
    {
        public Int32 x;
    }
 
    struct SomeVal     // Значимый тип (поскольку 'struct')
    {
        public Int32 x;
    }
 
    struct SomeVal2     // Значимый тип (поскольку 'struct')
    {
        public Int32 x;
    }
 
    public sealed class Program
    {
        static void Main(string[] args)
        {
        SomeRef r1 = new SomeRef(); // Размещается в куче
        SomeVal v1 = new SomeVal(); // Размещается в стеке
        SomeVal2 v2 = new SomeVal2();// Размещается в стеке
        r1.x = 5;                   // Разыменовывание указателя
        v1.x = 5;                   // Изменение в стеке
        v2.x = 7;
        Console.WriteLine(r1.x);    // Отображается "5"
        Console.WriteLine(v1.x);    // Также отображается "5"
        Console.WriteLine(v2.x);    // Отображается "7"
 
        Console.WriteLine(v1.Equals(r1));   //типы SomeVal и SomeRef не равны
        Console.WriteLine(r1.x.Equals(v1.x));//значения r1.x и v1.x равны
        Console.WriteLine(v1.Equals(v2));  //почему типы не равны???
    }
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.12.2015, 21:36
Ответы с готовыми решениями:

Переменные значимых типов
Помогите решить.

Использование переменных значимых типов
Здравствуйте, возникли проблемы в реализации программы на C#: Задание 1: Рассчитать значение функции в заданной точке. Использовать...

создание значимых типов в цикле
если в цикле создавать значимую переменную for (int i = 0; i < 1000; i++) { int k = 10; } то k создастся...

10
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18286 / 14209 / 5368
Регистрация: 17.03.2014
Сообщений: 28,888
Записей в блоге: 1
30.12.2015, 21:58
Baeron, для значимых типов можно не перегружать Equals т.к. для них автоматически делается сравнение значений. То есть делается побайтовое сравнение значений. При этом сравнение значений двух разных типов даст в любом случае ложь, что в общем-то логично. У тебя v1 имеет тип SomeVal, а v2 SomeVal2. Разумеется они не равны друг другу. Если обе переменные будут иметь одинаковый тип и одно значение, то они будут равны друг другу. Например так:
C#
1
2
3
SomeVal v1 = new SomeVal(); v1.x = 5;
SomeVal v2 = new SomeVal(); v2.x = 5;
Console.WriteLine(v1.Equals(v2));  // Истина
1
2 / 2 / 1
Регистрация: 22.09.2014
Сообщений: 132
30.12.2015, 22:48  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
сравнение значений двух разных типов даст в любом ложь
Перечитал на более свежую голову следующее (Рихтер 4-е мздание стр 154.)

Значимые типы являются производными от System.ValueType. Этот тип имеет
те же методы, что и System.Object. Однако System.ValueType переопределяет
метод Equals, который возвращает true, если значения полей в обоих объектах
совпадают
. Из-за проблем с производительностью в реализации по умол-
чанию, определяя собственные значимые типы значений, надо переопределить
и написать свою реализацию методов Equals и GetHashCode.


то есть он сравнивает значения полей а не их типы.
C#
1
Console.WriteLine(v1.Equals(r1));   //типы SomeVal и SomeRef не равны - false
Спасибо за помощь.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18286 / 14209 / 5368
Регистрация: 17.03.2014
Сообщений: 28,888
Записей в блоге: 1
30.12.2015, 23:03
Baeron, в моем ответе была ошибка. Там сравнивались значения разных типов и что было сказано что они будут равны. Это неправильно. Я имел в виду одинаковые типы. Пример уже исправлен на правильный.

Цитата Сообщение от Baeron Посмотреть сообщение
то есть он сравнивает значения полей а не их типы.
Типы самих полей нет необходимости сравнивать, но прежде чем переходить к сравнению полей метод Equals убеждается что он сравнивает одинаковые типы. Нет никакого смысла сравнивать double и long несмотря на то что оба занимают 8 байтов.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
30.12.2015, 23:16
Цитата Сообщение от OwenGlendower Посмотреть сообщение
для значимых типов можно не перегружать Equals
Можно, но лучше все-таки всегда перегружать, а заодно и реализовать IEquatable, потому как при дефолтной реализации имеют место:
а) запаковка/распаковка
б) рефлексия
1
2 / 2 / 1
Регистрация: 22.09.2014
Сообщений: 132
30.12.2015, 23:30  [ТС]
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Нет никакого смысла сравнивать double и long
нет смысла сравнивать если вызнаете, какие типы содержит ваш класс, а если нет, или класс не ваш???
Не понятно зачем Джефри сделал акцент на этом переопределении и что хотел сказать.
Что мы сравниваем? Типы полей которые содержит или значения полей?
В чем суть этого переопределения?

странно и то что
вот такой код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SomeRef r1 = new SomeRef(); // Размещается в куче
            SomeRef r2 = new SomeRef();
            SomeVal v1 = new SomeVal(); // Размещается в стеке
            SomeVal2 v2 = new SomeVal2();
            r1.x = 5;                   // Разыменовывание указателя
            r2.x = 7;
            v1.x = 5;                   // Изменение в стеке
            v2.x = 7;
            Console.WriteLine(r1.x);    // Отображается "5"
            Console.WriteLine(v1.x);    // Также отображается "5"
            Console.WriteLine(v2.x);
 
            Console.WriteLine(r1.Equals(r2));
            Console.WriteLine(r1.x.Equals(r2.x));
            Console.WriteLine(v1.Equals(r1));   //типы SomeVal и SomeRef не равны
            Console.WriteLine(r1.x.Equals(v1.x));//значения r1.x и v1.x равны
            Console.WriteLine(v1.Equals(v2));
в строке
C#
1
            Console.WriteLine(r1.Equals(r2));
тоже выдаст false - хотя я же пытаюсь сравнить методом
C#
1
public virtual bool Equals(Object obj);
который принимает obj - а в моем случае этот obj - это тип SomeRef.

P.S. конечно Equals удобен для сравнения именно значений, но если говорить о типах, неужели это не востребовано?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
30.12.2015, 23:47
Для reference типов реализация Equals по умолчанию сравнивает ссылки, поэтому и false.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18286 / 14209 / 5368
Регистрация: 17.03.2014
Сообщений: 28,888
Записей в блоге: 1
30.12.2015, 23:52
Цитата Сообщение от Baeron Посмотреть сообщение
нет смысла сравнивать если вызнаете, какие типы содержит ваш класс, а если нет, или класс не ваш???
Нет смысла сравнивать камень с яблоком. Если типы структур разные, то неважно что у них внутри.

Цитата Сообщение от Baeron Посмотреть сообщение
Не понятно зачем Джефри сделал акцент на этом переопределении и что хотел сказать.
Думаю он хотел подчеркнуть отличие значимых типов от ссылочных в рамках операции сравнения.

Цитата Сообщение от Baeron Посмотреть сообщение
Что мы сравниваем? Типы полей которые содержит или значения полей?
Значение.

Цитата Сообщение от Baeron Посмотреть сообщение
P.S. конечно Equals удобен для сравнения именно значений, но если говорить о типах, неужели это не востребовано?
Что именно не востребовано?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
30.12.2015, 23:53
Baeron, я не совсем понимаю, в чем же вы запутались... Все же просто и логично, разве нет?
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;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            SomeRef refObj1 = new SomeRef { X = 10, Y = 10 };
            SomeRef refObj2 = new SomeRef { X = 10, Y = 10 };
 
            SomeVal valObj1 = new SomeVal { X = 10, Y = 10 };
            SomeVal valObj2 = new SomeVal { X = 10, Y = 10 };
 
            Console.WriteLine(refObj1.Equals(refObj2));
            Console.WriteLine(valObj1.Equals(valObj2));
            Console.ReadLine();
        }
    }
    class SomeRef {
        public int X;
        public int Y;
    }
    struct SomeVal {
        public int X;
        public int Y;
    }
}
В первом случае результат False, во втором True, как и должно быть...
1
2 / 2 / 1
Регистрация: 22.09.2014
Сообщений: 132
31.12.2015, 00:31  [ТС]
Цитата Сообщение от insite2012 Посмотреть сообщение
В первом случае результат False, во втором True
так почему именно так???
P.S. ответ перечитаю отром на свежую голову. спасибо за помощь ;-)
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
31.12.2015, 00:37
Лучший ответ Сообщение было отмечено Baeron как решение

Решение

Цитата Сообщение от Baeron Посмотреть сообщение
так почему именно так???
В первом случае у нас ссылочный тип. Метод Equals мы не перегружали, и сравниваются ссылки.
Во втором случае у нас тип значения (поскольку это struct), а он наследует от System.ValueType, в котором уже переопределен Equals (вместо нас), и тут уже идет сравнение значений, а не ссылок.
Все же вроде ясно и понятно...
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
31.12.2015, 00:37
Помогаю со студенческими работами здесь

Аргументы значимых типов в обобщениях с ограничениями на конструктор
Здравствуйте! Подскажите, пожалуйста, почему обобщённому типу, с ограничением на конструктор, можно передавать аргументы значимых типов,...

Динамическое приведение значимых типов данных из строки
У меня есть значимый целочисленный тип данных (type). Есть строковая переменная (str), в которой должно быть записано значение типа type....

Метод Equals
Подскажите, что делает данная ф-ция. Есть Arr(массив) и поле data(данные) public override bool Equals(object obj) { ...

Реализовать метод equals() для класса
class Bus{ protected String type; }

Как определить метод equals для своих обетов?
Если создал свой класс нужно перерисовать в нем этот метод или есть другие выходы?


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru