Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/41: Рейтинг темы: голосов - 41, средняя оценка - 4.56
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517

Перегрузить оператор ==, но не потерять возможности сравнения с null

11.07.2012, 16:13. Показов 7915. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как перегрузить оператор == для класса, но так чтобы проверка на null осталась работоспособной.
Потому как если я перегружаю оператор == в классе
C#
1
2
3
4
        public static bool operator == (Person one, Person two)
        {
            return one.age == two.age;
        }
А потом пытаюсь сделать это

C#
1
2
3
Person oldest = null;
...
if (oldest == null) //вылет. Оно логично, ведь я пытаюсь обратиться к полю age у null"
Перегрузка оператора == в виде
C#
1
2
3
4
5
6
7
        public static bool operator == (Person one, Person two)
        {
            if (one == null || two == null)//проверить на null
                return false;
 
            return one.age == two.age;
        }
Ничего не даёт, теперь получается что я в оператор == вызываю оператор == что тоже плохо, так как же проверить адрес, а не сам объект?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.07.2012, 16:13
Ответы с готовыми решениями:

Не получается перегрузить оператор сравнения
class vremya { private: int h,m,s; public: void operator ++(int) { s++; if (s==60) ...

Для шаблонного класса перегрузить оператор присваивания, copy-конструктор, объекты cin и cout, оператор *
Помогите в следующем: Для класса шаблона следует перегрузить оператор присваивания, конструктор копирования, бинарный оператор суммы «*»,...

Перегрузить операторы сравнения и отсортировать
Добрый день. Требуется отсортировать данные из файла формата "тип1 тип2 тип3 тип4" только по "тип1" и "тип2" (в...

17
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
11.07.2012, 16:18
Gepar,
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
    internal class Program
    {
        public class Person
        {
            public int age { get; set; }
            public static bool operator ==(Person one, Person two)
            {
                if ((Object)one == null || (Object)two == null)//проверить на null
                    return false;
 
                return one.age == two.age;
            }
            public static bool operator !=(Person one, Person two)
            {
                if ((Object)one == null || (Object)two == null)//проверить на null
                    return true;
 
                return one.age != two.age;
            }
            public Person()
            {
                this.age = 10;
            }
        }       
 
        private static void Main(string[] args)
        {
            Person p1 = new Person();
            Person p2 = new Person();
            Console.WriteLine(p1==p2); // Output: True
            Console.ReadKey();
        }
    }
2
 Аватар для buntar
543 / 544 / 181
Регистрация: 16.03.2012
Сообщений: 1,160
Записей в блоге: 2
11.07.2012, 16:20
C#
1
2
3
4
5
6
public static bool operator == (Person one, Person two)
{
 if (one == null || two == null)
    return false;
return true;
}
0
 Аватар для Lasur
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
11.07.2012, 16:55
Один из вариантов - приведение к object для сравнения, как предложил Psilon.
Еще возможно использование ReferenceEquals:
C#
1
2
3
4
5
6
7
8
public static bool operator ==(Person a, Person b)
        {
            if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
                //return false;
                //При сравнении null vs null лучше возвращать true.
                return ReferenceEquals(a, b);
            return a.age == b.age;
        }
2
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2012, 17:08  [ТС]
buntar, и что же ты изменил? Проверку то оставил ту же самую.
Psilon, твой вариант тоже не работает, по прежнему будет ошибка получаться. Приведу ка я весь код наверное. Код весьма прост, хоть и не очень короткий, это учебный пример так что допустимость значений проверяется только там где это важно для работоспособности кода, а не корректности результатов. Проблема возникает лишь с оператором == и последующим его (случайным) использованием при сравнении с null.

1) Вариант который собирается (оператор == и != закомментирован потому и собирается !)
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace People
{
    public class Person
    {
        private string name;
        private int age;
 
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
 
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
            }
        }
 
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
 
        public override string ToString()
        {
            return name + ", " + age;
        }
 
 
        public static bool operator >(Person one, Person two)
        {
            return one.Age > two.Age;
        }
 
        public static bool operator <(Person one, Person two)
        {
            return !(one > two);
        }
 
        /*
        public static bool operator == (Person one, Person two)
        {
            if (one == null || two == null)
                return false;
 
            return one.age == two.age;
        }
       
 
        
        public static bool operator != (Person one, Person two)
        {
            return ! (one == two);
        }
        
        */
 
        public static bool operator >= (Person one, Person two)
        {
            return (one>two || one.age == two.age);
        }
 
        public static bool operator <=(Person one, Person two)
        {
            return (one < two || one.age == two.age);
        }
    }
 
 
 
    //хранит объекты Person, как ключ будет служить имя персоны
    public class People : DictionaryBase, ICloneable
    {
        public void Add(Person toAdd)
        {
            Dictionary.Add(toAdd.Name, toAdd);
        }
 
        public void Remove(Person toRemove)
        {
            Dictionary.Remove(toRemove.Name);
        }
 
        
        public Person this[string key]
        {
            get
            {
                return (Person)Dictionary[key];
            }
        }
 
 
        //для for each
        public new IEnumerator GetEnumerator()
        {
            foreach (object person in Dictionary.Values)
                yield return (Person)person;
        }
 
 
        //возвращает массив самых старших персон (количество элементов зависит от того
        //у скольки персон наибольший возраст совпадёт)
        public Person[] GetOldest()
        {
            int count = 0;
            Person oldest = null;
 
            foreach (object value in Dictionary.Values)
                //если oldest ещё ничего не назначалось то можно считать
                //что любая персона по сравнению с null объектом старше
                if (oldest == null) //ВЫВАЛИТСЯ ЕСЛИ ПЕРЕГРУЗКА ОПЕРАТОРА == БУДЕТ ДОСТУПНА
                    oldest = value as Person;
                //иначе сохраняем указатель только если текущая персона старше
                else if (value as Person > oldest)
                    oldest = value as Person;
 
            if (oldest != null)
            {
                foreach (object value in Dictionary.Values)
                    if ((value as Person).Age == oldest.Age)
                        count++;
 
                Person[] result = new Person[count];
                foreach (object value in Dictionary.Values)
                    if ((value as Person).Age == oldest.Age)
                        result[--count] = value as Person;
                return result;
            }
 
            return null;
        }
 
        public object Clone()
        {
            People newPeople = new People();
            foreach (Person pers in Dictionary.Values)
                newPeople.Dictionary.Add(pers.Name, pers);
 
            return newPeople;
        }
    }
 
 
 
    class Program
    {
        static void Main(string[] args)
        {
            People pp = new People();
            pp.Add(new Person("Adam", 22));
            pp.Add(new Person("Eva", 18));
            pp.Add(new Person("Andy", 22));
            pp.Add(new Person("Hero", 22));
 
            Person[] res = pp.GetOldest();
 
            if(res != null)
            foreach (Person pers in res)
                Console.WriteLine(pers);
        }
    }
}
Вариант 2:тоже самое но оператор == , != расскомментированы. Ошибка происходит когда идёт проверка на null в функции GetOldest класса People.

Добавлено через 4 минуты
С ReferenceEquals сработало. Перегрузка приняла вид
C#
1
2
3
4
5
6
7
8
9
10
        
        public static bool operator == (Person one, Person two)
        {
            if (ReferenceEquals(one, null) && ReferenceEquals(two, null))
                return true;
            else if (ReferenceEquals(one, null) || ReferenceEquals(two, null))
                return false;
 
            return one.age == two.age;
        }
и теперь учитываются оба варианта (когда идёт сравнение с null и когда оба объекта null).

Добавлено через 2 минуты
Хотя с приведениями к Object тоже сработало, нужно только обе проверки было сделать чтобы было так:
C++
1
2
3
4
5
6
7
8
9
        public static bool operator == (Person one, Person two)
        {
            if ((Object)one == null && (Object)two==null)
                return true;
            else if ((Object)one == null || (Object)two == null)
                return false;
 
            return one.age == two.age;
        }
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
11.07.2012, 17:08
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace People
{
    public class Person
    {
        private string name;
        private int age;
 
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
 
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
            }
        }
 
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
 
        public override string ToString()
        {
            return name + ", " + age;
        }
 
 
        public static bool operator >(Person one, Person two)
        {
            if ((object)one == null || (object)two == null)
                return false;
            return one.Age > two.Age;
        }
 
        public static bool operator <(Person one, Person two)
        {
            return !(one > two);
        }
 
        
        public static bool operator == (Person one, Person two)
        {
            if ((object)one == null || (object)two == null)
                return false;
 
            return one.age == two.age;
        }
       
 
        
        public static bool operator != (Person one, Person two)
        {
            if ((object)one == null || (object)two == null)
                return false;
            return one.age != two.age;
        }
        
 
        public static bool operator >=(Person one, Person two)
        {
            return (one > two || one.age == two.age);
        }
 
        public static bool operator <=(Person one, Person two)
        {
            return (one < two || one.age == two.age);
        }
    }
 
 
 
    //хранит объекты Person, как ключ будет служить имя персоны
    public class People : DictionaryBase, ICloneable
    {
        public void Add(Person toAdd)
        {
            Dictionary.Add(toAdd.Name, toAdd);
        }
 
        public void Remove(Person toRemove)
        {
            Dictionary.Remove(toRemove.Name);
        }
 
 
        public Person this[string key]
        {
            get
            {
                return (Person)Dictionary[key];
            }
        }
 
 
        //для for each
        public new IEnumerator GetEnumerator()
        {
            foreach (object person in Dictionary.Values)
                yield return (Person)person;
        }
 
 
        //возвращает массив самых старших персон (количество элементов зависит от того
        //у скольки персон наибольший возраст совпадёт)
        public Person[] GetOldest()
        {
            int count = 0;
            Person oldest = null;
 
            foreach (object value in Dictionary.Values)
                //если oldest ещё ничего не назначалось то можно считать
                //что любая персона по сравнению с null объектом старше
                if (oldest == null) //ВЫВАЛИТСЯ ЕСЛИ ПЕРЕГРУЗКА ОПЕРАТОРА == БУДЕТ ДОСТУПНА
                    oldest = value as Person;
                //иначе сохраняем указатель только если текущая персона старше
                else if (value as Person > oldest)
                    oldest = value as Person;
 
            if (oldest != null)
            {
                foreach (object value in Dictionary.Values)
                    if ((value as Person).Age == oldest.Age)
                        count++;
 
                Person[] result = new Person[count];
                foreach (object value in Dictionary.Values)
                    if ((value as Person).Age == oldest.Age)
                        result[--count] = value as Person;
                return result;
            }
 
            return null;
        }
 
        public object Clone()
        {
            People newPeople = new People();
            foreach (Person pers in Dictionary.Values)
                newPeople.Dictionary.Add(pers.Name, pers);
 
            return newPeople;
        }
    }
 
 
 
    class Program
    {
        static void Main(string[] args)
        {
            People pp = new People();
            pp.Add(new Person("Adam", 22));
            pp.Add(new Person("Eva", 18));
            pp.Add(new Person("Andy", 22));
            pp.Add(new Person("Hero", 22));
 
            Person[] res = pp.GetOldest();
 
            if (res != null)
                foreach (Person pers in res)
                    Console.WriteLine(pers);
        }
    }
}
0
11.07.2012, 17:08  [ТС]

Не по теме:

deleted

0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
11.07.2012, 17:11
Gepar, да, как раз хотел уточнить, что при такой организации null не участвует в упорядочивании. Сами догадались
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
11.07.2012, 17:13
Не забудьте также переопределить метод Equals и GetHashCode, чтобы не было неоднозначности в сравнении двух экземпляров.
0
 Аватар для Lasur
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
11.07.2012, 17:19
Цитата Сообщение от Gepar Посмотреть сообщение
С ReferenceEquals сработало. Перегрузка приняла вид
C#
1
2
3
4
5
6
7
8
9
10
        
        public static bool operator == (Person one, Person two)
        {
            if (ReferenceEquals(one, null) && ReferenceEquals(two, null))
                return true;
            else if (ReferenceEquals(one, null) || ReferenceEquals(two, null))
                return false;
 
            return one.age == two.age;
        }
и теперь учитываются оба варианта (когда идёт сравнение с null и когда оба объекта null).
Зачем столько if - ов и else -ов. Мой код уже проверял все возможности:
C#
1
2
3
4
5
6
public static bool operator ==(Person a, Person b)
        {
            if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
                return ReferenceEquals(a, b);
            return a.age == b.age;
        }
Добавлено через 4 минуты
Цитата Сообщение от kolorotur Посмотреть сообщение
Не забудьте также переопределить метод Equals и GetHashCode, чтобы не было неоднозначности в сравнении двух экземпляров.
Если уж переопределять Object.Equals, то правильнее будет писать и Equals интерфейса IEquatable<Person>. А в этом случае, оператор сравнения, лучше уже переписывать на его основе...
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
11.07.2012, 17:23
Цитата Сообщение от Lasur Посмотреть сообщение
Если уж переопределять Equals, то правильнее будет писать и Equals интерфейса IEquatable
Не правильнее.
IEquatable и метод Equals класса object - это разные вещи.
По гайдлайнам при перегрузке оператора == и !=, также нужно переопределять метод Equals и GetHashCode - именно для постоянства реализации.
Если же хочется внести дополнительное понятие "равенства" или "эквивалентности" объектов, тогда уже можно реализовать IEquatable.
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2012, 17:33  [ТС]
Класс не претендует на "доделанный, протестированный и быстро работающий", как видите там и ToString() не перегружено даже для вывода объектов класса, я перфекционизмом не страдаю

Цитата Сообщение от kolorotur Посмотреть сообщение
По гайдлайнам при перегрузке оператора == и !=, также нужно переопределять метод Equals и GetHashCode
Вот тут кстати интересная вещь: код собирался и не жаловался ни на что, но стоило мне попытаться добавить ещё итерацию по Возрастам (Ages), те просто левую функцию возвращающую IEnumerator (то что добавил кстати не хочет вызываться ещё как планировал, но не суть), как VS внезапно вспомнила что я оператор == и != перегрузил, а вот Equals и GetHaskCode - нет. А ведь до этого молчала же.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
11.07.2012, 17:36
Цитата Сообщение от Gepar Посмотреть сообщение
Класс не претендует на "доделанный, протестированный и быстро работающий"
А класс и не должен на это претендовать.
На то, чтобы класс таковым являлся, должны претендовать вы, как разработчик этого класса.
В противном случае - вон из профессии

Цитата Сообщение от Gepar Посмотреть сообщение
код собирался и не жаловался ни на что, но стоило мне попытаться добавить ещё итерацию по Возрастам (Ages), те просто левую функцию возвращающую IEnumerator (то что добавил кстати не хочет вызываться ещё как планировал, но не суть), как VS внезапно вспомнила что я оператор == и != перегрузил, а вот Equals и GetHaskCode - нет. А ведь до этого молчала же.
Студия этим грешит время от времени.
Я пока точно не понял: что-то в коде не так или студийный парсер глючит, но тоже не раз замечал, что некоторые ворнинги генерируются при одном билде и пропадают на другом (без изменения кода).
1
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2012, 17:49  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
А класс и не должен на это претендовать.
На то, чтобы класс таковым являлся, должны претендовать вы, как разработчик этого класса.
В противном случае - вон из профессии
Я ленивый, попробовал пару раз перегрузить ToString() - получилось нормально вот и перестал перегружать во всех остальных классах заостряя внимание на ту тему которая описывается в текущей главе книги, в данном случае перегрузка операторов и итераторы. С остальным тоже самое, лень реализовывать по 100 раз тоже самое если это всего лишь учебный пример и он никому после его написания не понадобится.

Цитата Сообщение от kolorotur Посмотреть сообщение
Студия этим грешит время от времени.
А, ну тогда всё в порядке, ато я уже подумал было что в с# есть какой-то хитрый таракан в стиле "если у вас процессор Intel, а количество функций в классе больше 5 и вы перегрузили оператор == то вы обязаны перегрузить ещё и ...". Мало ли
0
 Аватар для Lasur
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
11.07.2012, 17:49
Цитата Сообщение от kolorotur Посмотреть сообщение
IEquatable и метод Equals класса object - это разные вещи.
По гайдлайнам при перегрузке оператора == и !=, также нужно переопределять метод Equals и GetHashCode - именно для постоянства реализации.
Если уж говорить о гайдлайнах - не так давно интересовался как нужно правильно использовать все возможные методы сравнения (static object.Equals, instance object.Equals, ReferenceEquals, Equals<T>, ==, !=). В итоге, побродив по просторам интернета, в частности по StackOverflow, наткнулся на книгу Effective C# в которой в деталях расписывался, в том числе, этот момент. Так вот, ее автор прямо настаивает на использовании обобщенного Equals в случае переопределения обычного.
В частности, он приводит следующую реализацию object.Equals:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Foo : IEquatable<Foo>
{
    public override bool Equals(object right)
    {
        if (object.ReferenceEquals(right, null))
            return false;
        if (object.ReferenceEquals(this, right))
            return true;
        if (this.GetType() != right.GetType())
            return false;
        return this.Equals(right as Foo);
    }
    public bool Equals(Foo other)
    {
        // ...
    }
}
Объекты разного типа редко считаются одинаковыми, посему обычному Equals удобнее вызывать Equals обобщенный после проверки на соответствие типов.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
11.07.2012, 18:03
Цитата Сообщение от Gepar Посмотреть сообщение
я уже подумал было что в с# есть какой-то хитрый таракан
Вполне может быть, что он действительно есть.
Но что студия время от времени, казалось бы, без причины то выдает, то не выдает ворнинги - случается.

Цитата Сообщение от Lasur Посмотреть сообщение
ее автор прямо настаивает на использовании обобщенного Equals в случае переопределения обычного.
Ну это примерно то же самое, что рекомендации вместе с интерфейсом IEnumerable<T> реализовывать так же IEnumerable.
Они отнюдь не лишены смысла, но студия ругаться не будет, если их оба не реализовывать.

Цитата Сообщение от Lasur Посмотреть сообщение
Объекты разного типа редко считаются одинаковыми
Я один и тот же тип имел в виду.
Конечно, если при разных обстоятельствах условия эквивалентности меняются, то тут лучше писать отдельный класс, реализующий IEqualityComparer для каждого условия.
0
 Аватар для Lasur
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
11.07.2012, 18:27
Цитата Сообщение от kolorotur Посмотреть сообщение
Я один и тот же тип имел в виду.
Конечно, если при разных обстоятельствах условия эквивалентности меняются, то тут лучше писать отдельный класс, реализующий IEqualityComparer для каждого условия.
Или я вас не понял, или вы меня... Под словами
Цитата Сообщение от Lasur Посмотреть сообщение
Объекты разного типа редко считаются одинаковыми, посему обычному Equals удобнее вызывать Equals обобщенный после проверки на соответствие типов.
я имел в виду следующее:
если мы перегружаем object.Equals(object obj), то ,чаще всего, попросту осуществляется попытка свести obj к типу нашего класса MyClass и потом производить нужные сравнения. Так вот логичнее всего вынести эти сравнения в Equals(MyClass obj).

Цитата Сообщение от kolorotur Посмотреть сообщение
Ну это примерно то же самое, что рекомендации вместе с интерфейсом IEnumerable<T> реализовывать так же IEnumerable.
Они отнюдь не лишены смысла, но студия ругаться не будет, если их оба не реализовывать.
Разве IEnumerable<T> не наследует IEnumerable? Кроме того, ругань студии охватывает довольно мало ситуаций... Например, у мелкомягких есть рекомендации по добавлению дополнительного статического метода для любого перегруженного оператора, но студия даже не заикается об этом...
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
11.07.2012, 19:08
Цитата Сообщение от Lasur Посмотреть сообщение
если мы перегружаем object.Equals(object obj), то ,чаще всего, попросту осуществляется попытка свести obj к типу нашего класса MyClass и потом производить нужные сравнения.
Так точно. Для этого дела даже паттерн есть.

Цитата Сообщение от Lasur Посмотреть сообщение
Так вот логичнее всего вынести эти сравнения в Equals(MyClass obj).
Полностью с вами согласен.
Но проблема возникает тогда, когда мы пытаемся наш сферический класс в вакууме, реализовавший IEquatable<MyClass>, передать ссылочкой в какой-нибудь метод, написанный до появления генериков (которых во фреймворке - пруд пруди).
Этот метод будет использовать Equals, определенный у object, а мы будем наблюдать странную работу приложения и чесать репу, размышляя, что за фигня тут творится

Цитата Сообщение от Lasur Посмотреть сообщение
Разве IEnumerable<T> не наследует IEnumerable?
Наследует. Я, честно сказать, тоже не вижу причину в такой рекомендации. Возможно, возникают какие-то сложности или непонятки в случае наследования и перереализации наследником этого интерфейса - вот и сделали из частного случая общую рекомендацию.
Но это так - мои домыслы о действительных причинах.

Цитата Сообщение от Lasur Посмотреть сообщение
у мелкомягких есть рекомендации по добавлению дополнительного статического метода для любого перегруженного оператора, но студия даже не заикается об этом...
Полезные рекомендации, кстати.
Но, говоря конкретно о ругани, - это рекомендации для написания CLS-compliant кода. Если вы пометите класс, перегружающий операторы, как CLS-compliant, то, я думаю, студия будет ругаться.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.07.2012, 19:08
Помогаю со студенческими работами здесь

Как перегрузить оператор<< и оператор>> ?
Доброго времени суток. Застрял на двух вопросах и не как не могу найти инфу которвя мне помогла бы их решить. вопрос первый. В общем...

Проиллюстрировать возможности операций отношения (сравнения)
#include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; int main() { int a,b,c,d,n,m,x; setlocale(0,&quot;&quot;); cout...

Для класса Vector перегрузить операторы присваивания, сравнения, ввода и вывода
срочно помогите написать программу, желательно с комментариями если можно)) Для класса Vector перегрузить операторы присваивания, ...

Как перегрузить методы Equals() и GetHashCode(), для сравнения свойств объектов?
Есть два объекта класса Квадрат.Необходимо сравнить их по площади заданной свойством. Для этого необходимо перегрузить операторы == и !=....

Как перегрузить операции отношения для реализации значимой семантики сравнения объектов
Добрый вечер, уважаемые участники форума. Есть поставленная задача с наследованием: Она в некотором роде не дописана (последние два...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru