Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to await a null literal?

You can await anything in C# 5+ so long as the type has a function called .GetAwaiter() that returns a special object or has a extension method that does the same.

Unity3d in its next major release is going to be supporting async/await. Currently in Unity3d you can yield return null; inside a coroutine to represent "Wait for next frame".

I was wondering if it is possible to craft a extension method that would allow you to do await null; to get the same behavior. There is no System.Null like there is a System.Void, so I could not think of what type to put in the extension method.

like image 896
Scott Chamberlain Avatar asked Jan 04 '17 00:01

Scott Chamberlain


2 Answers

You are right that yield and await are closely related. Both are points in a workflow where the current method is paused, control is returned to the caller, and the method resumes at an unspecified point in the future at the point where the yield / await happened.

But they are very different in terms of their action on their operands. They are in fact duals of each other. A yield provides a new value when demanded by the code iterating the sequence. An await extracts a value when it is produced by the asynchronously executing task.

Null is a perfectly valid value, so it makes sense for a yield to proffer it up to its caller. But null is not a valid task, and so it makes no sense for await to attempt to extract the value from the task.

Currently in Unity3d you can yield return null; inside a coroutine to represent "Wait for next frame".

In an async-await asynchronous workflow the analog of yield return null; is just return null;. That means "end this portion of the asynchronous workflow by providing the null reference". Why are you not simply returning null if you intend to produce a task whose result is null?

Let me put it another way that might be more clear. Obviously this makes no sense:

foreach(var x in null)
   Console.WriteLine(x);

This is identically nonsensical:

var x = await null;
Console.WriteLine(x);

These are the same thing logically. Foreach means "extract a value from the sequence as long as values are available", but null is not a sequence. Similarly, "await" means "extract a value from the task as soon as a value is available", but null is not a task.

That's the key: the asynchronous analog of await is not yield return, it's foreach. That's the mechanism that extracts the T from the IEnumerable<T> or Task<T>. The thing that puts the T into the monadic type is yield return for IEnumerable<T> and return for Task<T>.

like image 80
Eric Lippert Avatar answered Sep 25 '22 17:09

Eric Lippert


There's no way to define an extension method on a literal null, since a literal null has no type:

.. we realized that the null type was bizarre. It is a type with only one value — or is it? Is the value of a null nullable int really the same as the value of a null string? And don’t values of nullable value type already have a type, namely, the nullable value type?

And:

Therefore we removed references to the useless “null type” in the C# 3.0 specification.

like image 36
Blorgbeard Avatar answered Sep 26 '22 17:09

Blorgbeard