Форум программистов, компьютерный форум, киберфорум
Наши страницы

C# для начинающих

Войти
Регистрация
Восстановить пароль
 
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
#1

StackOverflowException в перегрузке оператора == - C#/.NET 2.x

24.07.2013, 15:26. Просмотров 616. Ответов 14
Метки нет (Все метки)

Есть абстрактный класс Catalog
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
public abstract class Catalog
{
    /// <summary>
    /// Возвращает серию каталога.
    /// </summary>
    protected virtual int Series
    {
        get { return 0; }
    }
 
    #region Equality members
 
    private bool Equals(Catalog other)
    {
        return Series == other.Series;
    }
 
    /// <summary>
    /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
    /// </summary>
    /// <returns>
    /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
    /// </returns>
    /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param>
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != GetType()) return false;
        return Equals((Catalog)obj);
    }
 
    /// <summary>
    /// Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"/> is suitable for use in hashing algorithms and data structures like a hash table.
    /// </summary>
    /// <returns>
    /// A hash code for the current <see cref="T:System.Object"/>.
    /// </returns>
    public override int GetHashCode()
    {
        return Series.GetHashCode();
    }
 
    #endregion
 
    public static bool operator ==(Catalog cat1, Catalog cat2)
    {
        return cat1 != null && (cat2 != null && cat1.Equals(cat2));
    }
 
    public static bool operator !=(Catalog cat1, Catalog cat2)
    {
        return !(cat1 == cat2);
    }
}
Есть два класса наследника, которые имеют разное свойство Series и больше в них ничего нет.

Хотел сделать сравнение двух экземпляров класса Catalog, которое возвращало бы true, если в экземлярах одни и те же классы наследники. Перед сравнением делал проверку на null, но на ней вылетел StackOverflowException
C#
1
2
3
4
5
6
Catalog _cat;
...
If (_cat != null)
{
   ...
}
Что я делаю не так?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.07.2013, 15:26
Я подобрал для вас темы с готовыми решениями и ответами на вопрос .NET 2.x StackOverflowException в перегрузке оператора == (C#):

Еще раз о перегрузке оператора ++ - C#
Привет. Прочитал аналогичные темы на форуме. И все равно не получается: Реализую перегрузку оператора ++ class Triangle ...

Альтернатива перегрузке оператора присваивания - C#
Я знаю, что перегрузка оператора присваивания в C# не возможна. Мне нужно найти альтернативный способ для решения следующей задачи,...

Вываливается EXEPTION при перегрузке оператора. Порядок действий внизу - C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace...

Ошибка "Доступ только для чтения" при перегрузке оператора - C#
Выскакивает такая вот ошибка. В чем может быть дело?

StackOverFlowException - C#
Есть простенькое приложение, настолько простое что не могу понять откуда там ошибкам взяться, тем не менее StackOverFlowException в...

StackoverflowException - C#
Есть класс в котором куча стринговых переменных с значениями и 5 простых. Пробовал уменьшать кол-во переменных до 24, но ошибка вылезает...

14
Kruds
694 / 694 / 106
Регистрация: 04.03.2013
Сообщений: 1,384
Завершенные тесты: 1
24.07.2013, 15:52 #2
У вас программа зацикливается между != и ==, имхо лучше так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Equals(Catalog cat) долой
public override bool Equals(object obj)
        {
            if (obj is Catalog)
                return this.Series == (obj as Catalog).Series;
            else return false;
        }
public static bool operator ==(Catalog cat1, Catalog cat2)
        {
            return cat1.Equals(cat2);
        }
 
public static bool operator !=(Catalog cat1, Catalog cat2)
        {
            return !(cat1 == cat2);
        }
1
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
24.07.2013, 17:03  [ТС] #3
Теперь nullReferenceException

у null может Equals вызываться?
0
Kruds
694 / 694 / 106
Регистрация: 04.03.2013
Сообщений: 1,384
Завершенные тесты: 1
24.07.2013, 18:02 #4
Ссылка ни на что не указывает, для чего Equals вызывать?
0
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
24.07.2013, 18:30  [ТС] #5
Цитата Сообщение от Kruds Посмотреть сообщение
Ссылка ни на что не указывает, для чего Equals вызывать?
В смысле?
0
Kruds
694 / 694 / 106
Регистрация: 04.03.2013
Сообщений: 1,384
Завершенные тесты: 1
24.07.2013, 18:54 #6
Ссылка, как известно, указывает на участок памяти. Ссылка со значением null не указывает ни на что, поэтому попытка разыменовать ее приводит к такому исключению, проще говоря нельзя считать значение из ниоткуда.
1
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
24.07.2013, 19:04  [ТС] #7
Просто я сейчас понял, что проверять равенство экземпляра_со_значением_null c самим null для любого объекта с помощью == я могу, а вот с помощью .Equals - нет, так ведь?
Собственно мне надо добавить обработку null-значений в == типа этого
C#
1
if (ReferenceEquals(cat1, null)) return false;
Ход моих мыслей верный?
0
Kruds
694 / 694 / 106
Регистрация: 04.03.2013
Сообщений: 1,384
Завершенные тесты: 1
24.07.2013, 19:32 #8
В таком случае да, достаточно дополнить перегрузку оператора == проверкой cat1 на null.
1
Psilon
Master of Orion
Эксперт .NET
5935 / 4834 / 636
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
24.07.2013, 19:56 #9
Вот так должно выглядеть переопределение равенства
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
public class MyClass
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Z { get; set; }
 
        public static bool operator ==(MyClass one, MyClass other)
        {
            return !ReferenceEquals(one, null) && one.Equals((object) other);
        }
 
        public static bool operator !=(MyClass one, MyClass other)
        {
            return !(one == other);
        }
 
        protected bool Equals(MyClass other)
        {
            return X == other.X && Y == other.Y && Z == other.Z;
        }
 
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((MyClass) obj);
        }
 
        public override int GetHashCode()
        {
            unchecked
            {
                int hashCode = X;
                hashCode = (hashCode*397) ^ Y;
                hashCode = (hashCode*397) ^ Z;
                return hashCode;
            }
        }
    }
}
1
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
25.07.2013, 10:58  [ТС] #10
Psilon, добавил в перегрузку операции ==, иначе не сравнить с null
C#
1
2
3
4
if (ReferenceEquals(one, null) && ReferenceEquals(other, null))
        {
            return true;
        }
0
Psilon
Master of Orion
Эксперт .NET
5935 / 4834 / 636
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
25.07.2013, 11:35 #11
Что не сравнить? Этот код работает для всех возможных комбинаций...
0
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
25.07.2013, 11:48  [ТС] #12
C#
1
2
3
4
5
MyClass myObj;
if (myObj == null)
{
 
}
Если у меня объект не инициализирован или равен null, то сравнения с null не будет, всегда будет возвращаться false
C#
1
2
3
4
public static bool operator ==(MyClass one, MyClass other)
        {
            return !ReferenceEquals(one, null) && one.Equals((object) other);
        }
0
Psilon
Master of Orion
Эксперт .NET
5935 / 4834 / 636
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
25.07.2013, 17:43 #13
Lupus, и что?http://msdn.microsoft.com/ru-ru/library/dd183755


1. x.Equals(x) возвращает значение true. Это называется свойством рефлексивности.

2. x. Equals (y) возвращает то же значение, что и y. Equals (x). Это называется свойством симметрии.

3. Если (x.Equals(y) && y.Equals(z)) возвращает true, то x.Equals(z) возвращает true. Это называется свойством транзитивности.

4. Последовательные вызовы x.Equals (y) возвращают одно и то же значение до тех пор, пока объекты, на которые ссылаются x и y, не будут изменены.

5. x.Equals(null) возвращает значение false. Однако null.Equals(null) вызывает исключение; эта инструкция не удовлетворяет приведенному выше правилу номер 2.
Добавлено через 1 минуту
Так что у меня первое сравнение то излишне, нужно вызывать просто
C#
1
2
3
4
public static bool operator ==(MyClass one, MyClass other)
        {
            return one.Equals((object) other);
        }
0
Lupus
23 / 23 / 1
Регистрация: 13.03.2011
Сообщений: 326
25.07.2013, 18:11  [ТС] #14
Цитата Сообщение от Psilon Посмотреть сообщение
Lupus, и что?
То что, все (которыми я пользуюсь) стандартные классы .Net позволяют мне сравнивать неиницилизированные экземпляры с null, а экземпляр класса в Вашем примере будет выдавать exeption.
Собственно, именно поэтому в примере по Вашей ссылке операция == прегружена по другому
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static bool operator ==(TwoDPoint lhs, TwoDPoint rhs)
            {
                // Check for null on left side.
                if (Object.ReferenceEquals(lhs, null))
                {
                    if (Object.ReferenceEquals(rhs, null))
                    {
                        // null == null = true.
                        return true;
                    }
 
                    // Only the left side is null.
                    return false;
                }
                // Equals handles case of null on right side.
                return lhs.Equals(rhs);
            }
0
Psilon
Master of Orion
Эксперт .NET
5935 / 4834 / 636
Регистрация: 10.07.2011
Сообщений: 14,439
Записей в блоге: 5
Завершенные тесты: 4
25.07.2013, 18:12 #15
Lupus, у мс всегда так: дают рекомендации, и тут же их нарушают.
0
25.07.2013, 18:12
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.07.2013, 18:12
Привет! Вот еще темы с ответами:

System.StackOverflowException - C#
Создал рекурсивную функцию. Рекурсию нужно использовать в четырех местах, в общем, код ниже. Программа работает адекватно, если оставляю...

StackOverflowException в Interface - C#
Здравствуйте! Есть два интерфейса в разных .cs namespace Deposit { interface IPerson { int...

System.StackOverflowException - C#
class Program { class Man { public int age { get; set; } public...

.NET 4.x System.StackOverflowException - C#
public string name { get { return name; } set { if (value != null)name = value; } } Результат...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru