Почему я получаю исключение переполнения стека? - PullRequest
1 голос
/ 13 октября 2010

Ниже приведена простая тестовая программа, которая выдает StackOverflowException при вызове Equals. Я ожидал, что универсальный Equals, полученный от объекта, вызовет мой IEquatable<MyClass>.Equals, но он этого не делает, вместо этого он вызывает сам себя. Зачем? Тип параметра, кажется, в порядке. Почему он называет универсальную версию в первую очередь? Я в замешательстве.

using System;

namespace consapp
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass x0 = new MyClass("x0");
            MyClass x1 = new MyClass("x");

            Console.WriteLine(x1.Equals(x0));
        }

    }

    internal class MyClass : IEquatable<MyClass>
    {
        public string Name { get; set; }
        public MyClass(string s) { this.Name = s; }
        public override bool Equals(object x) { return this.Equals(x as MyClass); }
        public override int GetHashCode() { return this.Name.ToLowerInvariant().GetHashCode(); }
        bool IEquatable<MyClass>.Equals(MyClass x) { return x != null && this.Name == x.Name; }
    }
}

Ответы [ 4 ]

9 голосов
/ 13 октября 2010

IEquatable.Equals реализовано явно.Сначала необходимо привести класс к интерфейсу, чтобы использовать явную реализацию:

public override bool Equals(object x) 
{ 
  return (this as IEquatable).Equals(x as MyClass); 
}

В противном случае он будет продолжать вызывать себя в бесконечной рекурсии, что в конечном итоге приведет к исключению StackoverflowException.

1 голос
/ 13 октября 2010

public override bool Equals(object x) { return this.Equals(x as MyClass); }
Приведенная выше строка вызывает его.

Вам придется изменить его на

public override bool Equals(object x) 
{ 
    return ((IEquatable<MyClass>)this).Equals(x as MyClass); 
}
0 голосов
/ 13 октября 2010

Попробуйте

public override bool Equals(object x) {
    Console.Write("equals! ");
    return this.Equals(x as MyClass);

}
0 голосов
/ 13 октября 2010

Если вы хотите вызвать Equals объекта в своем переопределении Equal, вам следует вызвать base.Equals, а не this.Equals.

И учтите, что Equals объекта просто сравнивает ссылки, а не содержимое.

...