Overload resolution simplification

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Aug 15 05:30:36 PDT 2013


Here's an example in C# that features similar problems as the 
Comparator.comparing case (I beg your mercy for my horrible C# skills :-)):

class Test<T>
{
     delegate object Delegate1<X>(X s);
     delegate string Delegate2<Y>(Y s);

     static Test<Z> m<Z>(Delegate1<Z> d1) { return null; }
     static Test<Z> m<Z>(Delegate2<Z> d2) { return null; }

     static void test()
     {
         Test<string> ts = m((x)=>"");
     }
}

We have two overloads, each accepting a slightly different delegate; the 
two delegates are generic (like our comparing SAMs) and they differ only 
in the return type - Delegate2 has a more specific return type. Both 
methods return a Test<Z>, where Z is the same type-variable used to 
parameterize the delegate. If I compile this with my crappy mono 
compiler I get:

Test.cs(11,27): error CS0411: The type arguments for method 
`Test<T>.m<Z>(Test<T>.Delegate1<Z>)' cannot be inferred from the usage. 
Try specifying the type arguments explicitly

Which seems to be in sync with my understanding of Eric's posts. You 
need to supply another argument to unblock inference for the lambda 
body; otherwise the body won't be used. I.e. this works:

class Test<T>
{
     delegate object Delegate1<X>(X s);
     delegate string Delegate2<Y>(Y s);

     static Test<Z> m<Z>(Delegate1<Z> d1, Z z) { return null; } 
//additional param here
     static Test<Z> m<Z>(Delegate2<Z> d2, Z z) { return null; } 
//additional param here

     static void test()
     {
         Test<string> ts = m((x)=>"", ""); //additional actual here
     }
}

So, while I don't trust my unofficial C# compiler too much, this seems 
to confirm that C# has similar boundaries to what we have in Java. It 
just happens to be less of an issue in C# where there are much less 
overloads because of primitives.

Maurizio

On 15/08/13 10:30, Ali Ebrahimi wrote:
> Hi,
> This [1] is another post from Eric.
>
> [1] 
> http://ericlippert.com/2012/10/02/how-do-we-ensure-that-method-type-inference-terminates/
>
>
> On Thu, Aug 15, 2013 at 4:12 AM, Ali Ebrahimi 
> <ali.ebrahimi1781 at gmail.com <mailto:ali.ebrahimi1781 at gmail.com>> wrote:
>
>     Hi,
>
>     On Thu, Aug 15, 2013 at 1:59 AM, Maurizio Cimadamore
>     <maurizio.cimadamore at oracle.com
>     <mailto:maurizio.cimadamore at oracle.com>> wrote:
>
>         On 14/08/13 19:57, Ali Ebrahimi wrote:
>
>             Hi,
>             please reread Eric's last two paragraph again[1]:
>
>         I think I read it well - I just believe Eric is talking about
>         two different  kinds of information flow:
>
>         1) return type constraints on methods cannot influence
>         overload resolution [as in Java]
>
>         2) lambda return value constraints CAN influence overload
>         resolution [as in Java]
>
>
>     3) lambda return value constraints CAN also influence type
>     inference (as in C#, based on my understandings from C#'s Spec &
>     Eric's blog)
>
>
>         The big question mark is: how do I get to a lambda return
>         value constraint? Well, you have to be able to check the
>         lambda first; and when can you do that?
>
>     when you don't turn off type inference.
>
>         When you have a grip on the _instantiated_ lambda parameter
>         types. This, I believe, means that in certain cases,
>         restriction (1) will play an important factor, as certain
>         lambdas will not be checked (or will be checked with
>         sub-optimal parameter types?) and you won't get what you
>         expect. More or less what you get with Comparator.comparing.
>
>
>     Regards,
>     Ali Ebrahimi
>
>



More information about the lambda-spec-observers mailing list