当前位置: 首页 > 编程语言 > C#

为什么我不能使用反射来改变Type.Delimiter?Share

时间:2023-04-10 21:07:19 C#

为什么我不能使用反射更改Type.Delimiter?如果我想更改bool.TrueString的值,我会使用反射:typeof(bool).GetField("TrueString",BindingFlags.Public|BindingFlags.Static).SetValue(null,"Yes");Console.WriteLine(bool.TrueString);//Outputs"Yes"但是,我无法设置更改Type.Delimiter的值:typeof(Type).GetField("Delimiter",BindingFlags.Public|BindingFlags.Static).SetValue(null,'-');Console.WriteLine(Type.Delimiter);//输出“.”这是为什么?我认为您正在成为JIT执行的优化的牺牲品。您实际上可以更改此字段的值,但由于某些原因,更改的结果不会立即可见。我设法通过做一些愚蠢的事情来解决这个问题:typeof(Type).GetField("Delimiter",BindingFlags.Public|BindingFlags.Static).SetValue(null,'-');FuncgetDelimiter=()=>输入.Delimiter;Console.WriteLine(getDelimiter());此代码可靠地显示字段的更新值。我不能说我很惊讶;该字段被声明为只读,因此JITter可以在访问该字段时使用该假设。你正在做一些顽皮和邪恶的事情,不应该期望它以理智的方式工作。现在,至于为什么在修改bool.TrueString字段时它没有出现,我最好的猜测是由于bool.TrueString是引用类型(string),而Type.Delimiter是值类型(char)。我可以想象这会触发不同的优化。我确实看过这段代码的反汇编:Console.WriteLine(bool.TrueString);006F2E538B0DB8104003movecx,dwordptrds:[34010B8h]006F2E59E852A67754call54E6D4B0Console.WriteLine(Type.Delimiter);006F2E5EB92E000000movecx,2Eh006F2E63E8B0FAE054call55502918您可以清楚地看到Type.Delimiter通过将其替换为字面值'.'来优化Type.Delimiter字段访问。.'.bool.TrueStringbool.TrueString的静态字段访问仍然从实际字段加载。区别在于bool.TrueString是引用类型,Type.Delimiter是值类型。对这两个属性尝试相同的代码,您会看到相同的行为:publicclassA{publicstaticreadonlystringS="S";publicstaticreadonlycharC='C';发生这种情况是因为,第一次调用该方法时,JIT编译器会计算静态只读值是否可以作为常量直接添加到汇编代码中。如果可以,它会这样做。如果访问字段的代码被提取到另一个方法中,其输出将取决于它的第一次运行是在字段值更改之前还是之后。由于您的代码都采用相同的方法,因此在字段值更改之前,它显然是JIT化的。您会发现,如果您使用可以硬编码到面向CPU的指令中的值类型,则会应用此JIT优化。这包括int、long和char的东西,但不包括DateTime或strings之类的引用类型以上是C#学习教程:为什么我不能使用反射来改变Type.Delimiter?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: