Wie wäre es, wenn Sie kein Keyword hätten?
Ich möchte, dass der Compiler erkennt, dass ich in den meisten Fällen, wenn ich eine asynchrone Methode aufrufe, das Ergebnis davon haben möchte.
Document doc = DownloadDocumentAsync();
Das ist es. Der Grund, warum die Leute Schwierigkeiten haben, sich ein Schlüsselwort für diese Sache auszudenken, ist, dass es so ist, als hätte man ein Schlüsselwort für "Mach das, was du machen würdest, wenn die Dinge vollkommen normal wären". Dies sollte die Standardeinstellung sein und kein Schlüsselwort erfordern.
Aktualisieren
Ich schlug ursprünglich vor, dass der Compiler mit der Typinferenz klug werden sollte, um herauszufinden, was zu tun ist. Wenn Sie dies weiter überlegen, würde ich die vorhandene Implementierung im CTP beibehalten, aber ein paar triviale Ergänzungen vornehmen, um die Fälle zu reduzieren, in denen Sie das await
Schlüsselwort explizit verwenden müssten .
Wir erfinden ein Attribut: [AutoAwait]
. Dies kann nur auf Methoden angewendet werden. Eine Möglichkeit, dies auf Ihre Methode anzuwenden, besteht darin, es zu markieren async
. Sie können es aber auch von Hand machen, zB:
[AutoAwait]
public Task<Document> DownloadDocumentAsync()
In einer beliebigen async
Methode geht der Compiler dann davon aus DownloadDocumentAsync
, dass Sie auf einen Aufruf von warten möchten , sodass Sie ihn nicht angeben müssen. Jeder Aufruf dieser Methode wartet automatisch darauf.
Document doc = DownloadDocumentAsync();
Wenn Sie nun "clever" werden und die erhalten möchten Task<Document>
, verwenden Sie einen Operator start
, der nur vor einem Methodenaufruf angezeigt werden kann:
Task<Document> task = start DownloadDocumentAsync();
Ordentlich, denke ich. Jetzt bedeutet ein einfacher Methodenaufruf, was es normalerweise bedeutet: Warten Sie, bis die Methode abgeschlossen ist. Und start
weist auf etwas anderes hin: Warten Sie nicht.
Bei Code, der außerhalb einer async
Methode angezeigt wird, können Sie eine Methode nur aufrufen, [AutoAwait]
indem Sie ihm ein Präfix voranstellen start
. Dadurch müssen Sie Code schreiben, der dieselbe Bedeutung hat, unabhängig davon, ob er in einer async
Methode enthalten ist oder nicht.
Dann werde ich gierig! :)
Erstens möchte ich mich async
auf Schnittstellenmethoden beziehen:
interface IThing
{
async int GetCount();
}
Dies bedeutet im Grunde, dass die implementierende Methode zurückkehren muss Task<int>
oder etwas Kompatibles await
, und dass Aufrufer der Methode [AutoAwait]
Verhalten erhalten.
Auch wenn ich die obige Methode implementiere, möchte ich schreiben können:
async int GetCount()
Task<int>
Als Rückgabetyp muss ich also nicht erwähnen .
Außerdem möchte ich mich async
auf Delegiertypen anwenden (die schließlich wie Schnittstellen mit einer Methode sind). So:
public async delegate TResult AsyncFunc<TResult>();
Ein async
Delegierter hat - Sie haben es erraten - [AutoAwait]
Verhalten. Von einer async
Methode aus können Sie sie aufrufen und sie wird automatisch await
bearbeitet (es sei denn, Sie wählen nur start
diese). Und wenn Sie sagen:
AsyncFunc<Document> getDoc = DownloadDocumentAsync;
Das funktioniert einfach Es ist kein Methodenaufruf. Es wurde noch keine Aufgabe gestartet - eine async delegate
ist keine Aufgabe. Es ist eine Fabrik für Aufgaben. Sie können sagen:
Document doc = getDoc();
Damit wird eine Aufgabe gestartet und es wird gewartet, bis sie abgeschlossen ist und Sie das Ergebnis erhalten. Oder du kannst sagen:
Task<Document> t = start getDoc();
Wenn Sie also eine async
Methode delegieren möchten , müssen Sie wissen, wie man einen async delegate
Typ verwendet. Also anstatt Func
du musst sagen AsyncFunc
, und so weiter. Eines Tages könnte dies durch eine verbesserte Typinferenz behoben werden.
Eine andere Frage ist, was passieren soll, wenn Sie sagen, dass Sie mit einer normalen (nicht asynchronen) Methode beginnen. Offensichtlich wäre ein Kompilierungsfehler die sichere Option. Es gibt aber auch andere Möglichkeiten.