0

I have a class that overrides the addition operator twice. One that takes the type parameter and one that takes a double:

public class A<T>
{
    public A() { }

    public static A<T> operator +(A<T> a, T t)
    {
        Console.WriteLine("Generic add called.");
        return new A<T>();  // return to keep the compiler happy
    }

    public static A<T> operator +(A<T> a, double d)
    {
        Console.WriteLine("Double add called.");
        return new A<T>();  // return to keep the compiler happy
    }
}

When the class is parameterized by the int type, it behaves as expected:

A<int> aInt = new A<int>();

var test = aInt + 3;
// -> Generic add called.

test = aInt + 3.0;
// -> Double add called.

But when parameterized by the double type, the non-generic add is called:

A<double> aDouble = new A<double>();

var otherTest = aDouble + 3.0;
// -> Double add called.

Assuming this behavior is the norm, I know which will be called. The non-generic override will be preferred. That said...

Will the non-generic method be always be preferred in the event of a collision?


All of the above code is available, runnable in your browser, here


EDIT: This question is related, but it's asking about generic methods, not classes. He gives this code:

class A
{
    public static void MyMethod<T>(T myVal) { }
    public static void MyMethod(int myVal) { }
}

which does not apply to my usage examples. Distinguishing between a.MyMethod(3) and a.MyMethod<int>(3) is obvious - one is generic and one is not.

Community
  • 1
  • 1
kdbanman
  • 10,161
  • 10
  • 46
  • 78
  • As far as I understand, specific methods will always be preferred against generic ones – Matias Cicero Jul 30 '15 at 16:09
  • possible duplicate of [Generic methods and method overloading](http://stackoverflow.com/questions/3679562/generic-methods-and-method-overloading) – Tyree Jackson Jul 30 '15 at 16:20
  • @TyreeJackson, the questions are different. I'm asking about generic classes, he's asking about generic methods. See my edit. However, Eric Lippert *does* answer my question in his large, multipart answer.. So, nonduplicate question with direct answer elsewhere. What should I do? – kdbanman Jul 30 '15 at 17:05
  • I'll quote and summarize the part of that answer that's actually relevant to my question in a self-answer. I think that makes sense. – kdbanman Jul 30 '15 at 17:09

2 Answers2

0

Simple answering yes. The compiler assume that because you have treated by hand a particular type parameter, that means that it has some special logic for you. That's why the second operator is called. To say further, operators are nothing more than static methods that accepts some parameters. For your case it's a binary operator so the static method has two parameters.

George Lica
  • 1,798
  • 1
  • 12
  • 23
  • Your explanation is reasonable, and it does happen to represent the common case. But the behavior is actually unspecified. – kdbanman Jul 30 '15 at 17:20
  • The CLR team made a lot of hidden assumptions and burned some default behaviours in the compiler. Some are somehow based on common sense, others are a little strange – George Lica Jul 30 '15 at 17:24
  • The big question is : what do you expect to happen? Given this situation i think that the behaviour is somehow intuitive – George Lica Jul 30 '15 at 17:29
  • I agree. It's very intuitive, and one of the class libraries I'm dependent upon uses it heavily, so let's hope it keeps working! Thanks for your answer. – kdbanman Jul 30 '15 at 17:44
0

The more specific method will be chosen, but that construction is a bad idea because it is technically unspecified behaviour.

To quote @EricLippert, substituting the code snippets for the ones from my question:

But the situation with [aDouble + 3.0] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.

Are there any examples of this sort of type construction causing truly implementation-defined behaviour?

Yes. See these articles for details:

http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx

http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx

Community
  • 1
  • 1
kdbanman
  • 10,161
  • 10
  • 46
  • 78