Verwenden eines generischen Typs als Rückgabetyp einer asynchronen Methode

8

Eine vorherige Frage ließ mich fragen, warum die folgende Methode einen Kompilierzeitfehler verursachen würde:

  

Der Rückgabetyp einer asynchronen Methode muss void sein, Task oder Task

%Vor%

Da wir zur Kompilierzeit wissen, dass T immer ein Task oder ein abgeleiteter Typ ist, warum funktioniert das nicht?

Bearbeiten

Der Grund, warum ich frage, ist, dass eine Methode möglicherweise eine Task oder eine Task<T> zurückgibt. Nehmen wir an, die Methode kann entweder zurückgeben und ich möchte keinen Code duplizieren.

Natürlich ist das alles theoretisch und nicht für Produktionszwecke geeignet.

Bearbeiten 2

Ich fand einen tollen Artikel von Lucian Wischik: Warum muss asynchrone Aufgabe zurückgegeben werden?

    
Yuval Itzchakov 29.05.2014, 17:32
quelle

2 Antworten

13

Drei Probleme:

  • Nur weil T " Task oder ein abgeleiteter Typ" ist, bedeutet das nicht, dass es Task oder Task<T> ist. Was würdest du erwarten, wenn ich MyMethodAsync<MyCustomTask> aufrufen würde, wo MyCustomTask von Task stammt?

  • Der Compiler muss wissen, ob er eine Zustandsmaschine baut, die Task oder Task<T> zurückgibt, wenn er die Methode kompiliert - er verwendet in den verschiedenen Fällen verschiedene Hilfsklassen

  • Wenn eine asynchrone Methode den Rückgabetyp Task hat, können alle return -Anweisungen keinen Wert angeben. Wenn es einen Rückgabetyp von Task<T> hat, müssen alle return -Anweisungen einen Wert angeben, der implizit in T umgewandelt werden kann. Wie kann das in MyMethodAsync funktionieren? Es ist ein bisschen so, als würde ich sagen "meine Methode ist entweder void oder gibt T zurück - Sie können entscheiden, wann Sie sie aufrufen".

Es ist nicht klar, was Sie hier erreichen wollen, aber im Grunde wird das nicht funktionieren.

    
Jon Skeet 29.05.2014, 17:37
quelle
-1

Ich kann mir keine gültige Definition von MyMethodAsync vorstellen, die es erlauben würde, ein generisches T von Task abzuleiten, ohne zu der Kompilierzeit zu wissen, was dieser Typ ist oder einen Parameter irgendeiner Art nimmt.

Wenn Sie wirklich Task oder Task<T> zurückgeben, können Sie Ihre Signatur aktualisieren, um diese Tatsache widerzuspiegeln und das Problem zu vermeiden.

Wenn Sie wirklich einen Typ brauchen, der von Task abgeleitet ist, dann müssen Sie Ihre Logik neu schreiben, um stattdessen Task oder Task<T> zurückzugeben und diesen anderen Typ zu umbrechen. Angenommen, das ist inakzeptabel, müssen Sie async löschen und den Zustandsautomaten selbst handhaben.

    
Guvante 29.05.2014 17:39
quelle

Tags und Links