1

Simply, are these two functions functionally exactly the same?

async Task SomeFuncAsync()
{
  await Task.Delay(1000);
}

async Task Foo1()
{
  await BarAsync();
  return SomeFuncAsync();
}

async Task Foo2()
{
  await BarAsync();
  await SomeFuncAsync();
}

If not, what is the difference?

(Note this is slightly different than this and this because I'm not considering removing async from my function signature. If this is a duplicate, please link and I'll delete.)

Rollie
  • 4,391
  • 3
  • 33
  • 55
  • 2
    In the second version you are not returning the results of `SomeFuncAsyn()`, so the first instance would return a `Task` where as the second version would return a Task where T = the return type of `SomeFuncAsync()` – Ryan Wilson Sep 14 '18 at 16:13
  • Ah, I actually meant Task with no return value `Task` rather than `Task<>`. I guess I should have specified that. – Rollie Sep 14 '18 at 16:15
  • I'd think the exception propagation would differ. – schar Sep 14 '18 at 16:16
  • @RyanWilson what is there to return? – Selman Genç Sep 14 '18 at 16:18
  • @RyanWilson Per your original comment, now both definitively return `Task` with no generic parameter (in the previous version, it was ambiguous and determined by the definition of `SomeFuncAsync`, which wasn't provided. – Rollie Sep 14 '18 at 16:19
  • Since everything returns a Task, there's no difference in your situation. – Poul Bak Sep 14 '18 at 16:20
  • 1
    The first `Foo1` returns a task wrapped in a task. That is because `async Task` signature will wrap the result in a Task as the return value. – Igor Sep 14 '18 at 16:20
  • @SelmanGenç There's your answer, it returns a `Task` – Ryan Wilson Sep 14 '18 at 16:22
  • 2
    Your edit wont compile… `Since 'Program.Foo1()' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'` – Rand Random Sep 14 '18 at 16:22
  • Good catch @RandRandom! I just assumed it would work since `Task` inherits from `Task`, so returning a `Task` should be fine in the above case (even with `T = Task`). I guess there's logic to prevent that though. – Rollie Sep 14 '18 at 16:31

1 Answers1

1

The first Foo1 returns a task wrapped in a task.

async Task Foo1()
{
  await BarAsync();
  return SomeFuncAsync();
}

That is because async Task signature will wrap the result in a Task as the return value. This happens because you are not awaiting the result. The proper return type in the signature though should be Task<Task>, not Task> because the code is returning something (in this case a Task).

async Task<Task> Foo1()
{
  await BarAsync();
  return SomeFuncAsync();
}

Once you correct the return type on this method the difference between it and the next method becomes more obvious. The first one returns a Task wrapped in a Task and the next one just returns a Task.

Igor
  • 60,821
  • 10
  • 100
  • 175