Stack overflow exception being generated in the instance method "Equals()"

Asked

Viewed 66 times

-2

I created a class called MyList<T>, with the intention of reproducing the class List, and I overwrote the method Equals to compare your instance with another of the same class, as follows:

class MyList<T> {
    
    // Código da classe...

    public override bool Equals(object obj) {
        
        if (obj is MyList<T>) {
            return Equals(obj, this);
        }
        return false;
    }

    public static bool Equals(MyList<T> listA, MyList<T> listB) {

        if (listA.Count != listB.Count) {
            return false;
        }
        for (long i = 0; i < listA.Count; i++) {
            if (!listA[i].Equals(listB[i])) {
                return false;
            }
        }
        return true;
    }
}

The problem is that whenever I try to check if one list is equal to another, the instance method Equals() enters an infinite loop and generates StackOverflowException with the following traceback:

Stack overflow.
Repeat 35393 times:
--------------------------------
   at MyList`1[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Equals(System.Object)
   at System.Object.Equals(System.Object, System.Object)
--------------------------------
   at MyList`1[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Equals(System.Object)
   at TestCSharp.Program.Main(System.String[])

If I use only the static method Equals(), passing the two instances of MyList<T>, verification occurs normally. That said, I believe the problem lies in the instance method.

Console.WriteLine(MyList<string>.Equals(list, list2)); // Retorna true ou false
Console.WriteLine(list.Equals(list2));                 // Stack Overflow

What am I doing wrong? Where is the cause of loop infinite?

  • Do you have any reason to be using long? List.Count is int...

  • @Luizfelipe I know, but I wanted my property as long with the intention that my list may contain more.

1 answer

3


The instance method is calling the wrong method by the overload resolution rules. This method is receiving an object of type Object and is passing to a method that waits Object, so it is not the static method Equal() that you wrote there in class, since he expects a MyList and not a Object, To resolve this you have to ensure that the call is made with an object MyList, making a cast.

This is a shame because version 1.0 of C# did not have adequate mechanisms and now pays an eternal price for it, in 2.0 it had the right mechanism, but it was too late.

Testing:

using static System.Console;

public class Program {
    public static void Main() {
        var x = new MyList<int>();
        var y = x;
        WriteLine(x.Equals(y));
    }
}

class MyList<T> {
    public override bool Equals(object obj) {
        WriteLine("instância");
        if (obj is MyList<T>) {
            return Equals((MyList<T>)obj, this);
        }
        return false;
    }

    public static bool Equals(MyList<T> listA, MyList<T> listB) {
        WriteLine("estático");
        return true;
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

As optimization could check if the references are equal, so do not need to check something costly. In general it is not advisable to create a method that will be adopted by the equality operator that could potentially take hours to execute.

  • What mechanisms do you refer to?

  • Mainly Generics.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.