If these two lines were equivalent:
string s = await File.ReadAllTextAsync(); // Current syntax
string s = File.ReadAllText(); // Proposed syntax
...then we would no longer be able to create a Task
without awaiting it immediately. So we couldn't do all these cool staff with Task.WhenAll
, Task.WhenAny
etc that allow concurrency. We would then need a different keyword to signify non-awaiting, like this:
var s = defer File.ReadAllText(); // s is Task<string>
Or infer it by the type of the return variable:
Task<string> s = File.ReadAllText(); // defer is inferred
Any method containing the line string s = File.ReadAllText();
would be now implicitly async, so it should return a Task
. For consistency, and to make it easier for the developers, it should probably allowed to preserve the unwrapped types in the signature. Example of equivalent current and proposed syntax:
public async Task<string> GetData() => await File.ReadAllTextAsync(); // Current syntax
public string GetData() => File.ReadAllText(); // Proposed syntax
I am not sure how far you can go with this experiment. I guess that if async
/await
had been introduced along with the TPL library, you could go some miles before hitting an obstacle. But since TPL (2010) predates async
/await
(2012), there were already lots of APIs exposing the Task
type, and lots of code using these APIs already that would be broken with the new syntax.