3

I have the following methods:

public void Say<TItem>(TItem item)
{
    Console.WriteLine("A");
}

public void Say<TItem>(IEnumerable<TItem> items)
{
    Console.WriteLine("B");
}

When I run the following:

void Main()
{
    Say<string>("Foo");
    Say(new string[] { "Foo", "Bar"});

}

The first method is invoked twice:

A
A

Note changing the IEnumerable<T> to a TItem[] does work as expected but in the case of the IEnumerable<T> why is it not picking up the second method? How can I achieve the intended overloading?

MaYaN
  • 6,683
  • 12
  • 57
  • 109

1 Answers1

6

Because it thinks that TItem is string[]. Look at this from the perspective of the compiler: All it knows is that it is looking for a generic type to plug into that method. It just so happens that string[] is a type. Because the meaning here is potentially ambiguous, you need to give the compiler some help to select which overload you are looking for here:

Say<string>(new string[]{"Foo", "Bar"});

should be enough to get it to select the method you actually wanted.

pquest
  • 3,151
  • 3
  • 27
  • 40
  • Great, but why is this extra help not required if the parameter type is `string[]` as opposed to `IEnumerable`? – MaYaN Aug 31 '16 at 21:59
  • 1
    @MaYaN In both cases your call could potentially match both signatures. When the method takes an `IEnumerable`, an implicit cast is needed to match, where for the other method requires no such cast. In the complier's mind, that makes the first overload a closer match. When you get more specific, the compiler is able to better infer what you were trying to do. – pquest Aug 31 '16 at 22:02