Статическое поле только для чтения не может быть присвоено
Вы не назначаете его.Вы вызываете публичные функции в пространстве имен System.Reflection
.У компилятора нет причин жаловаться на это.
Кроме того, typeof(string).GetField("Empty")
может вместо этого использовать переменные, введенные пользователем, у компилятора нет уверенного способа во всех случаях указать, является ли аргумент GetField
в итоге получится "Empty"
.
Я думаю, вы хотите, чтобы Reflection
увидел, что поле помечено initonly
, и выдает ошибку во время выполнения.Я могу понять, почему вы ожидаете, что даже для тестирования белого ящика даже запись в поля initonly
имеет какое-то применение.
Причина, по которой NGEN не имеет никакого эффекта, заключается в том, что вы не модифицируете здесь какой-либо код,только данные.Данные хранятся в памяти с .NET, как и с любым другим языком.Нативные программы могут использовать разделы памяти только для чтения для таких вещей, как строковые константы, но указатель на строку, как правило, все еще доступен для записи, и это то, что происходит здесь.
Обратите внимание, что ваш код должен работать с полным доверием, чтобы использоватьотражение в этом сомнительном пути.Кроме того, изменения затрагивают только одну программу, это не какая-то уязвимость безопасности, как вы думаете (если вы запускаете вредоносный код внутри вашего процесса с полным доверием, то решение по проекту является проблемой безопасности, а не отражением).
Также обратите внимание, что значения полей initonly
внутри mscorlib.dll
являются глобальными инвариантами среды выполнения .NET.После их разрушения вы даже не сможете надежно проверить, был ли нарушен инвариант, потому что код для проверки текущего значения System.String.Empty также сломался, потому что вы нарушили его инварианты.Начните нарушать системные инварианты, и на них нельзя полагаться.
Указав эти значения в спецификациях .NET, он позволяет компилятору реализовать целую кучу оптимизаций производительности.Простым является то, что
s == System.String.Empty
и
(s != null) && (s.Length == 0)
эквивалентны, но последний намного быстрее (условно говоря).
Также компилятор может определитьчто
if (int.Parse(s) > int.MaxValue)
никогда не имеет значения true и генерирует безусловный переход к блоку else (ему все равно приходится вызывать Int32.Parse
, чтобы иметь такое же поведение исключения, но сравнение можно удалить).
System.String.Empty
также широко используется в реализациях BCL.Если вы перезаписаете его, могут произойти все виды сумасшедших вещей, включая ущерб, который просачивается за пределы вашей программы (например, вы можете записать файл, имя которого построено с использованием манипуляций со строками ... при разрыве строки выможет перезаписать не тот файл)
И поведение может легко отличаться в разных версиях .NET.Обычно, когда обнаруживаются новые возможности оптимизации, они не переносятся обратно в предыдущие версии JIT-компилятора (и даже если бы они были, могут быть установки до того, как был создан обратный порт).Особенно.String.Empty
связанные оптимизации заметно различаются между .NET 2.x и Mono и .NET 4.5 +.