Eine vorherige Frage ließ mich fragen, warum die folgende Methode einen Kompilierzeitfehler verursachen würde:
%Vor%Der Rückgabetyp einer asynchronen Methode muss void sein, Task oder Task
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?
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.
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.
Tags und Links .net c# async-await generics