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 awaitSchlü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 asyncMethode 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 startweist auf etwas anderes hin: Warten Sie nicht.
Bei Code, der außerhalb einer asyncMethode 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 asyncMethode enthalten ist oder nicht.
Dann werde ich gierig! :)
Erstens möchte ich mich asyncauf 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 asyncauf Delegiertypen anwenden (die schließlich wie Schnittstellen mit einer Methode sind). So:
public async delegate TResult AsyncFunc<TResult>();
Ein asyncDelegierter hat - Sie haben es erraten - [AutoAwait]Verhalten. Von einer asyncMethode aus können Sie sie aufrufen und sie wird automatisch awaitbearbeitet (es sei denn, Sie wählen nur startdiese). Und wenn Sie sagen:
AsyncFunc<Document> getDoc = DownloadDocumentAsync;
Das funktioniert einfach Es ist kein Methodenaufruf. Es wurde noch keine Aufgabe gestartet - eine async delegateist 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 asyncMethode delegieren möchten , müssen Sie wissen, wie man einen async delegateTyp verwendet. Also anstatt Funcdu 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.