-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
System.FieldAccessException: Cannot set initonly static field #104242
Comments
Modifying the backing field of init-only properties has never been defined behavior. Reflection always has the possibility to break things, and what you are doing was unsupported. So it broke when you upgraded. The change to throw an exception was made such that, instead of silently failing in the future, it fails fast and load. If you want a singleton that is settable, just add a |
This is unsupported case. Many internal code are implying the immutability of static readonly fields and behave depend on them.
Private fields can be refactored away in any versions. There's strictly no guarantee that reflection on them can work across versions.
It's hard to be convenient. The behavior has been employed by different components, including the JIT. |
Tagging subscribers to this area: @dotnet/area-system-reflection |
As was mentioned there are ways to still mutate the underlying field, such as via
We have such similar things in our own code, we simply drop the The tests can then use a special helper that knows whether or not modifying the variable is supported:
Alternatively you can utilize features such as
The same general considerations exist here, it is fairly trivial to have an AppContext switch, environment variable, or other input to seed a |
Mutating initonly static fields using |
Right, that's why I made sure to call out that it's unsafe and can lead to UB.
This isn't just an optimization, but rather a fundamental expectation of the system and that impacts many areas from security, to robustness, and also performance. If you have something that is fundamentally not readonly, then you shouldn't mark it as such. |
The main ask was about components they don't own, including third party code and BCL types. There is no really reliable way to modify static readonly fields, but some simple cases may just run well. Using |
As others commented, this behavior is by design. The immutability of
If you need to modify behavior of .NET and 3rd-party components in ways that these components to do support natively, it is best to create your own build of those components with the required modifications, assuming that their license allows it. |
It did not work reliably in .NET Framework. .NET Framework ignored the new value of readonly variable some of the time. |
Description
The original issue:
#11571
dotnet/standard#1598
We faced the same issue when migrating from .NET Framework to .NET8.
Sorry, but this is a regression bug. I kindly ask you to provide the ability to disable optimizations and return the previous behavior to the ability to override static initonly fields.
You can provide any alternative, even a config for the built-in detours, but we need such an opportunity while .NET and third-party libraries use static initonly fields and properties.
Use cases:
Overriding the default behavior of .NET and 3rd-party types built around the use of static APIs such as ThreaPool. For example, we use this to impose an end-to-end limit on how many Parallel.ForEachs can run at the same time. At any time, you can carry out a refactoring that will make the readonly field we need and this technique will stop working.
Mock dependencies in tests. For example, we use a third-party library that provides an interface for interacting with DNS via a singleton. In tests, we need to replace the value of a static field.
Reproduction Steps
Expected behavior
The value is set correctly without errors.
Actual behavior
System.FieldAccessException: Cannot set initonly static field 'k__BackingField' after type 'Singleton' is initialized.
Regression?
Yes. It worked fine in the .NET Framework
Known Workarounds
There are no known workarounds because, based on the discussion in the linked issues, changing static fields after type initialization can lead to broken behavior due to optimizations already applied.
Configuration
.NET8
Other information
We kindly ask you to take the community's requests as seriously as possible. This "optimization" broke many packages and solutions. It comes out at the moment when the enterprise migrates from the old .NET Framework to the new .NET.
I am not asking you to roll back these changes (although I do ask you to analyze whether they are really needed).
But please provide a CONVENIENT option to disable them at the solution / build configuration level.
The text was updated successfully, but these errors were encountered: