Использование перегруженного оператора == в общей функции

Рассмотрим следующий код:

class CustomClass
{
    public CustomClass(string value)
        { m_value = value; }

    public static bool operator ==(CustomClass a, CustomClass b)
        { return a.m_value == b.m_value; }

    public static bool operator !=(CustomClass a, CustomClass b)
        { return a.m_value != b.m_value; }

    public override bool Equals(object o)
        { return m_value == (o as CustomClass).m_value; }

    public override int GetHashCode()
        { return 0; /* not needed */ }

    string m_value;
}

class G
{
    public static bool enericFunction1<T>(T a1, T a2) where T : class
        { return a1.Equals(a2); }
    public static bool enericFunction2<T>(T a1, T a2) where T : class
        { return a1==a2; }
}

Теперь, когда я вызываю обе общие функции, один успешно, а один не работает:

var a = new CustomClass("same value");
var b = new CustomClass("same value");
Debug.Assert(G.enericFunction1(a, b)); // Succeeds
Debug.Assert(G.enericFunction2(a, b)); // Fails

По-видимому, G.enericFunction2 выполняет реализацию по умолчанию operator == вместо моего переопределения. Может ли кто-нибудь объяснить, почему это происходит?

Ответ 1

От Ограничения по параметрам типа (Руководство по программированию на С#):

При применении ограничения класса T: избегайте операторов == и!= для параметра типа, поскольку эти операторы будут проверять только ссылочный идентификатор, а не на равенство значений. Это так, даже если эти операторы перегружены в типе, который используется в качестве аргумента. (...) Причиной такого поведения является то, что во время компиляции компилятор знает только, что T является ссылочным типом и поэтому должен использовать операторы по умолчанию, допустимые для всех ссылочных типов.

Ответ 2

Если я изменил значение enericFunction2 на:

    public static bool enericFunction2<T>(T a1, T a2) where T : class
    {
        object aa = a1;
        CustomClass obj1 = (CustomClass)aa;

        object bb = a2;
        CustomClass obj2 = (CustomClass)bb;

        return obj1 == obj2; 
    }

Тогда все работает нормально. Но я боюсь, что не могу это объяснить. Я имею в виду a1 и a2 знают их тип. Почему для CustomClass нужен актерский состав, поэтому вызываются операторы?