3

Given the following class:

public class Foo {
    public Foo(int i, double d) {
        Integer = i;
        Double = d;
    }
    public int Integer {get;}
    public double Double {get;}

    private static Random rand = new Random();
    public static Foo CreateRandom() => new Foo(rand.Next(1,101), rand.NextDouble());
}

As well as this usage:

void Main()
{
    var items = Enumerable.Range(0, 50)
                          .Select(_ => Foo.CreateRandom());

    Console.WriteLine(items.Sum(GetInteger)); // Fine
    Console.WriteLine(items.Sum(GetDouble)); // Ambiguous
    Console.WriteLine(items.Sum(x => x.Double)); // Also fine
    Console.WriteLine(items.Sum((Func<Foo,double>)GetDouble)); // Cast required? Why?

    int GetInteger(Foo item) => item.Integer;
    double GetDouble(Foo item) => item.Double;
}

I am trying to figure out why it is that the GetDouble delegate conversion is considered ambiguous, and what exactly makes it different in this context from the labmda expression and the cast to the anonymous delegate.

Edit: It looks like this does not affect C# 7.3, but does affect versions 7.2 and lower. Versions before local methods were added can be affected by making the GetInteger and GetDouble static.

Fabjan
  • 13,506
  • 4
  • 25
  • 52
Jonathon Chase
  • 9,396
  • 21
  • 39
  • 4
    please provide a [mcve] – Daniel A. White Nov 20 '18 at 18:24
  • I tried to compile your code and it worked without error message. Is there anything more in your test code? – Klaus Gütter Nov 20 '18 at 18:26
  • @JonathonChase Your code doesn't reproduce the problem described. The code compiles and runs just fine. – Servy Nov 20 '18 at 18:28
  • C# Interactive shell says `(1,25): error CS0121: The call is ambiguous between the following methods or properties: 'Enumerable.Sum(IEnumerable, Func)' and 'Enumerable.Sum(IEnumerable, Func)'` (edit: for `Console.WriteLine(items.Sum(GetDouble));`) – BurnsBA Nov 20 '18 at 18:32
  • 1
    Latest LINQPad update no longer replicates, my current installs of Rider and VS 2017 do. Not sure why. – Jonathon Chase Nov 20 '18 at 18:32
  • This glitch has been fixed in C# 7.3 Go to Build -> Advanced -> Language Version and change it to C# 7.3 – Fabjan Nov 20 '18 at 18:35
  • hmmm, `Func dd = (Foo x) => x.Double;` and then either `Enumerable.Sum(items, dd)` or `items.Sum(dd)`, both of those work. – BurnsBA Nov 20 '18 at 18:38

1 Answers1

5

What's new in C# 7.3

The following enhancements were made to existing features:

  • You can test == and != with tuple types.
  • You can use expression variables in more locations.
  • You may attach attributes to the backing field of auto-implemented properties.
  • Method resolution when arguments differ by in has been improved.
  • Overload resolution now has fewer ambiguous cases.

The last fix was for this issue. Before that compiler had more difficulties resolving overloads.

Here is a link to the source.

Fabjan
  • 13,506
  • 4
  • 25
  • 52