BanksySan
BanksySan

Reputation: 28500

C#6 Overload Resolution Func<T1> & Func<T2>

I know from this question\answer that the improvements in the overload resolution is that it includes the return type of a lambda in the resolution of the overload.

The example given on the site linked in the answer gives this:

class Program
{
    private static void TakesItem(Action item)
    {

    }
    private static int TakesItem(Func<int> item)
    {
        return item();
    }
    public static int somefunction()
    {
        return 50;
    }
    static void Main(string[] args)
    {
        int resultitem = TakesItem(somefunction);
        Console.WriteLine(resultitem);
        Console.ReadKey();
    }
}

This code will compile in version 6 and not in version 5.

I've tried changing it functions returning different types:

private void Foo(Func<int> func)
{
}

private void Foo(Func<string> func)
{

}

private int Bar()
{
    return 1;
}

[Test]
public void Example()
{
    Foo(Bar);
}

This doesn't compile in C# 6 though, despite the Func returning different values.

Upvotes: 3

Views: 81

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70652

It seems to me that the relevant part of the specification changes is here:

7.5.3.5 Better conversion target

Given two different types T1 and T2, T1 is a better conversion target than T2 if

•T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2>, D1 has a return type S1 and one of the following holds:
◦D2 is void returning
◦D2 has a return type S2, and S1 is a better conversion target than S2

Note that void-returning delegate types are special-cased. So in the new rules, Func<int> is a "better conversion target" than Action, because Action is void-returning.

In your second example, where there is still ambiguity, that is because the conversion doesn't meet any of the requirements stated. Both delegate types are not void-returning, and neither delegate type's return type is "better" than the other. That is, int is not "better than" string.

Note that int is "better than" object. So if you change the Func<string> to Func<object>, the compiler is able to choose and you no longer get the error.

Upvotes: 1

Related Questions