12

I am trying to get grasp of .NET 4.0+ Task Parallel Library concepts...

In the following C# 4.0 code snippet:

Task t = Task.Factory.StartNew(() =>
{
   Console.WriteLine("I am the task");
   return "res1";
});

why compiler doesn't (and run-time either) produce any error if the return cannot be used unless generic Task used instead:

Task<string> t = Task.Factory.StartNew(() =>
{
   Console.WriteLine("I am the task");
   return "res1";
});

Or it (returned object) can be used?

Do I understand correctly that <string> in Task<string> is needed only for detecting or assuring the type of return (ed object) or of t.Result?
Or there are any other hidden from me necessities except this?

Why this type cannot cannot be determined from the type of returned object?
I.e. why is the Result property of a task unavailable for non-generic tasks?

Fulproof
  • 4,466
  • 6
  • 30
  • 50

2 Answers2

21

The non-generic Task does not have a Result property because it represents a process that does not produce a result.

Your code creates a Task<string> in both cases, but in the first case you cast it to a Task (Task<string> derives from Task, so that's legal) and so you lose the ability to refer to the result.

You can see this directly with:

Task t = Task.Factory.StartNew(() =>
{
   Console.WriteLine("I am the task");
   return "res1";
});

var genericTask = t as Task<string>; // genericTask will be non-null
var result = genericTask.Result;     // and you can access the result
Jon
  • 428,835
  • 81
  • 738
  • 806
  • Yes, I saw it but I couldn't grasp why non-generic task cannot have `Result` property – Fulproof Mar 12 '13 at 11:25
  • 3
    @Fulproof It's conceptual thing. `Task` is more or less conceptually equivalent to `void` return type in async/Task world, whereas `Task` is equivalent to `T` return type. Now, given a method `void Foo()` you wouldn't try to do `var result = Foo();`, would you? :) – Patryk Ćwiek Mar 12 '13 at 11:28
  • Why, then, return-ing from non-generic Task "activity" isn't fetermined by compiler as an error or even warning? – Fulproof Mar 12 '13 at 11:34
  • @Fulproof There's a difference between a concept and the execution. If `void` was a *regular* type, then there would be no need for `Task`. But you can't do `Task`, so there's `Task` and the [class hierarchy](http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx) allows to return anything per Jon's answer. – Patryk Ćwiek Mar 12 '13 at 11:39
  • 1
    @Fulproof: Because *you are not returning from a non-generic `Task`*. You are returning from a generic `Task`, and then casting that into a non-generic task. – Jon Mar 12 '13 at 11:39
  • @Fulproof: `Task.StartNew` has [many overloads](http://msdn.microsoft.com/en-us/library/dd321421.aspx), and the one you are using returns a `Task`, not a plain `Task`. – Jon Mar 12 '13 at 11:41
0

Task<T> inherits from Task. In both cases you're actually creating a Task<T>, but in the first case you're implicitly casting it to Task, which doesn't have the Result property.

Eli Arbel
  • 22,391
  • 3
  • 45
  • 71