title: Ambiguous call between overloads of two-way implicit castable types when a derived type of one is passed as parameter
body: <p>(Trying to find a title that sums up a problem can be a very daunting task!)</p>
  
  <p>I have the following classes with some overloaded methods that produce a call ambiguity compiler error:</p>
  
  <pre><code>public class MyClass
  {
      public static void OverloadedMethod(MyClass l) { }
      public static void OverloadedMethod(MyCastableClass l) { }
  
      //Try commenting this out separately from the next implicit operator. 
      //Comment out the resulting offending casts in Test() as well.
      public static implicit operator MyCastableClass(MyClass l)
      {
          return new MyCastableClass();
      }
  
      //Try commenting this out separately from the previous implicit operator.
      //Comment out the resulting offending casts in Test() as well.
      public static implicit operator MyClass(MyCastableClass l)
      {
          return new MyClass();
      }
  
      static void Test()
      {
          MyDerivedClass derived = new MyDerivedClass();
          MyClass class1 = new MyClass();
          MyClass class2 = new MyDerivedClass();
          MyClass class3 = new MyCastableClass();
          MyCastableClass castableClass1 = new MyCastableClass();
          MyCastableClass castableClass2 = new MyClass();
          MyCastableClass castableClass3 = new MyDerivedClass();
  
          OverloadedMethod(derived); //Ambiguous call between OverloadedMethod(MyClass l) and OverloadedMethod(MyCastableClass l)
          OverloadedMethod(class1);
          OverloadedMethod(class2);
          OverloadedMethod(class3);
          OverloadedMethod(castableClass1);
          OverloadedMethod(castableClass2);
          OverloadedMethod(castableClass3);
  
      }
  
  public class MyDerivedClass : MyClass {  }
  
  public class MyCastableClass { }
  </code></pre>
  
  <p>There are two very interesting things to note:</p>
  
  <ol>
  <li>Commenting out any of the implicit operator methods removes the ambiguity.</li>
  <li>Trying to rename the first method overload in VS will rename the first four calls in the Test() method!</li>
  </ol>
  
  <p>This naturally poses two questions:</p>
  
  <ol>
  <li>What it the logic behind the compiler error (i.e. how did the compiler arrive to an ambiguity)?</li>
  <li>Is there anything wrong with this design? Intuitively there should be no ambiguity and the offending call should be resolved in the first method overload (<code>OverloadedMethod(MyClass l, MyClass r)</code>) as <code>MyDerivedClass</code> is more closely related to <code>MyClass</code> rather than the castable but otherwise irrelevant <code>MyCastableClass</code>. Furthermore VS refactoring seems to agree with this intuition.</li>
  </ol>
  
  <p><strong>EDIT:</strong>
  After playing around with VS refactoring, I saw that VS matches the offending method call with the first overload that is defined in code whichever that is. So if we interchange the two overloads VS matches the offending call to the one with the <code>MyCastableClass</code> parameter. The questions are still valid though.</p>