8

I've got really simple code:

static void Main(string[] args)
{
    var task = Task.Factory.StartNew(GetInt);

    var task2 = Task.Factory.StartNew(
        () =>
        {
            return GetInt();
        });
}

static int GetInt()
{
    return 64;
}

Why do I get a compiler error for the first task? The method signatures (no params, return type is int) are equal, aren't they?

I know a solution(which is quite simple: var task = Task.Factory.StartNew<int>(GetInt);) but I'd like to know whats the problem with the code above.

GameScripting
  • 16,092
  • 13
  • 59
  • 98
  • Please try yourself, I only have the german compiler error text: `Der Aufruf unterscheidet nicht eindeutig zwischen folgenden Methoden und Eigenschaften: "System.Threading.Tasks.TaskFactory.StartNew(System.Func)" und "System.Threading.Tasks.TaskFactory.StartNew(System.Action)"` but it doesn't make sense cause `GetInt` will return `int` not `void` – GameScripting Apr 05 '12 at 19:02

6 Answers6

3

You get an ambiguous call error because the method signature is the same. Return values are not part of the signature.

Since you don't provide an explicit return type, the compiler doesn't know which to take.

Method Signature in C#

Community
  • 1
  • 1
Alex
  • 7,901
  • 1
  • 41
  • 56
  • 1
    I think you really need to rephrase your answer: Action is very much a different type than Func. Your answer currently reads as if the `StartNew` implementation should not even compile. – ChrisWue Apr 05 '12 at 19:07
3

Because the compiler cannot decide which of these two overloads to use:

StartNew(Action)
StartNew<TResult>(Func<TResult>)

The reason for that is that the return type is not part of the overload resolution in C# (same way as you can't have two overloads only differing in return types) and therefore the compiler cannot decide whether GetInt should be an Action or a Func<T>. Forcing to use the generic version by calling StartNew<int>(GetInt) will provide the required information.

ChrisWue
  • 18,612
  • 4
  • 58
  • 83
2

For the record, here are two more ways of doing it (that compile):

var task3 = Task.Factory.StartNew((Func<int>)GetInt);
var task4 = Task.Factory.StartNew(() => GetInt());
Douglas
  • 53,759
  • 13
  • 140
  • 188
1

Would help to show the exception: "The call is ambiguous between the following methods or properties: 'System.Threading.Tasks.TaskFactory.StartNew(System.Action)' and 'System.Threading.Tasks.TaskFactory.StartNew(System.Func)'"

If you take a look there are two possible methods:

public Task<TResult> StartNew<TResult>(Func<TResult> function);
public Task StartNew(Action action);

If you add the <int> or supply a Func<int> you force it to take the first signature. Without that your code is ambiguous.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
0

You get the compile error because the StartNew method takes in either an Action (returns void) or a Func (returns something) predicates with it's various overloads, and not a direct delegate.

Scorpion-Prince
  • 3,574
  • 3
  • 18
  • 24
  • 1
    That sounds like a "hand-waving" answer, providing `` for the generic type parameter does not in any way make the delegate more like `Action` or `Func`, so obviously it is able to deduce that part itself. – Lasse V. Karlsen Apr 05 '12 at 18:59
  • Providing makes the call totally unambiguous. There is no signature `Task StartNew(Action)`. – Ian Mercer Apr 05 '12 at 19:04
  • @LasseV.Karlsen, Not sure why you would think so. I get 2 compile time errors when I compile the code - the first one says the return type for GetInt is not right. Therefore you need to rewrite the call as `code` var task2 = Task.Factory.StartNew(() => GetInt());`code` which is the abbreviated version of `code`var task = Task.Factory.StartNew(new Func(GetInt);`code`. – Scorpion-Prince Apr 05 '12 at 19:15
0

As stated by others, you need to pass in GetInt as a function to StartNew, or specify that you intend to return a value from StartNew by supplying the generic type. Otherwise, the compiler has no idea what kind of task you intend to create....it is ambiguous.

static void Main(string[] args)
{
    var task = Task.Factory.StartNew<int>(GetInt);

    var task2 = Task.Factory.StartNew(
        () =>
        {
            return GetInt();
        });
}

static int GetInt()
{
    return 64;
}
Eric Dahlvang
  • 8,252
  • 4
  • 29
  • 50