Replies: 6 comments
-
static IEnumerator Iterator()
{
Span<byte> buf = stackalloc byte[1]; // this is allowed in VS 15.5
buf[0] = 1;
yield return null;
Span<byte> bufOverYield = stackalloc byte[1];
yield return null;
bufOverYield[0] = 1; // this is not.
} So,
|
Beta Was this translation helpful? Give feedback.
-
to @ufcpp : |
Beta Was this translation helpful? Give feedback.
-
In iterators, this already works currently, as long as the variable isn't hoisted (isn't used before and after a yield): // Compiles
IEnumerator M() {
Span<byte> buf = stackalloc byte[1];
buf[0] = 1;
yield return null;
}
// Does not compile and that's expected
IEnumerator M() {
Span<byte> buf = stackalloc byte[1];
yield return null;
buf[0] = 1; // error CS4013
} So let's focus on async methods, where this doesn't compile: // Does not compile, but could
async void M() {
Span<byte> buf = stackalloc byte[1]; // error CS4012
buf[0] = 1;
await Task.Yield();
} The difference between iterators and async methods is small, both are compiled to a state machine and share a bunch of the same code generation. Async methods have some extras preliminary checks, where any restricted type (ref structs, TypedReference, etc.) isn't allowed as a parameter or a local. So I've tried to remove this limitation, and to my surprise this was really easy, by simply removing the locals check: https://github.com/MrJul/roslyn/commit/aa9184da4448457030a5c24e47426fe4627cb51c With the changes: // Now compiles
async void M() {
Span<byte> buf = stackalloc byte[1];
buf[0] = 1;
await Task.Yield();
}
// Does not compile and that's expected
async void M() {
Span<byte> buf = stackalloc byte[1];
await Task.Yield();
buf[0] = 1; // error CS4013
} The existing state machine transformation code is used in both places, and a CS4013 error is generated as soon as the local escapes, so everything works as expected. Note that this doesn't change the rule for restricted parameters, because they would have to be used only before the first await, which doesn't seem useful. This change has two other impacts:
|
Beta Was this translation helpful? Give feedback.
-
Is this useful? With more types becoming ref structs, such as Utf8JsonWriter, allowing the following code doesn't seem too far fetched to me:
|
Beta Was this translation helpful? Give feedback.
-
IMHO this is very useful. At this moment you have to create another method which will do that "synchronous" data manipulation for you. Would be nice to have ability to work with ref structs inside async and iterator methods. But as i mentioned - usage (as well as visibility of declared ref variables) could be limited in between different async/yield steps. The best way to do so is force developer to limit its visibility by scope bracers so your code will be like:
|
Beta Was this translation helpful? Give feedback.
-
Sadly, it's still not implemented |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Example:
Beta Was this translation helpful? Give feedback.
All reactions