-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Async method on struct mutating copy #4135
Comments
In short: unfortunately, it is impossible to implement this mutation in CLR :) In C#, we have some protection from this kind of struct mutability confusion when using closures inside struct declaration members: struct S {
public int Value;
void M() {
Action f = () => {
Value ++; // CS1673
};
}
}
Since execution of every closure can be arbitrarily delayed, we need some way to also delay the lifetime of all the members captured into closure. There is no way to do it in general for In theory, when value type is stored as a field of some managed object/element of array, C# can emit closure code to do struct mutation inplace. Unfortunately, there is no knowledge on where Unfortunately, different decision was made for iterator methods declared on using System.Collections;
struct S {
int Value;
IEnumerable I() {
Value++;
yield break;
}
} This code compiles fine and always operates on Absolutely the same story happens with |
Actually, you are not even allowed to do that (ECMA-335 section II.14.4.2):
The problem does indeed seem impossible to solve. Seems the compiler would have to pass the structure itself by reference to the enumerator returned, or do something clever with operating on a boxed instance and then unbox it by itself. I definitely think the compiler should emit a warning if it cannot be a compiler error because of backwards compatibility. The compiler magic right now makes for some pretty confusing behavior. |
We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages. See also #18002 for a general discussion of closing and/or moving language issues out of this repo. |
Following this question on SO: http://stackoverflow.com/questions/31642535/structs-private-field-value-is-not-updated-using-an-async-method/31646624#31646624
The following program will print 35, and not 45. This happens because the async generated state machine lifts a copy of the struct by copying the
this
parameter.I know that using mutable structs are evil, but still, this can lead to some confusion. Was this intentional behavior?
This is the decompiled method:
The text was updated successfully, but these errors were encountered: