Why async / await allows for implicit conversion from a List to IEnumerable?

前端 未结 3 1775
野趣味
野趣味 2021-02-12 03:47

I\'ve just been playing around with async/await and found out something interesting. Take a look at the examples below:

// 1) ok - obvious
public Task

        
3条回答
  •  一生所求
    2021-02-12 04:17

    Clearly you understand why List can at least be returned as IEnumerable: simply because it implements that interface.

    Also clearly, the 3rd example is doing something "extra" that the forth one isn't. As others have said, the 4th fails because of the lack of co-variance (or contra-, I can never remember which way they go!), because you are directly trying to offer an instance of Task> as an instance of Task>.

    The reason the 3rd passes is because await adds a big bunch of "backing code" to get it to work as intended. This code resolves the Task into T, such that return await Task will return the type closed in the generic Task, in this case something.

    That the method signature then returns Task and it works is again solved by the compiler, which requires Task, Task, or void for async methods and simply massages your T back into a Task as part of all the background generated asyn/await continuation gubbins.

    It is this added step of getting a T from await and needing to translate it back into a Task that gives it the space it needs to work. You are not trying to take an existing instance of a Task to satisfy a Task, you are instead creating a brand new Task, giving it a U : T, and on construction the implicit cast occurs as you would expect (in exactly the same way as you expect IEnumerable myVar = new List(); to work).

    Blame / thank the compiler, I often do ;-)

提交回复
热议问题