gpt4 book ai didi

c# - 为什么我不能使用反射更改 Type.Delimiter?

转载 作者:太空狗 更新时间:2023-10-29 23:13:07 27 4
gpt4 key购买 nike

如果我要更改 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); // Outputs "."

这是为什么?

最佳答案

我认为您正在成为 JIT 执行的优化的牺牲品。您实际上可以更改该字段的值,但由于某种原因,该更改的结果不会立即可见。我通过做一些愚蠢的事情设法解决了这个问题:

typeof(Type).GetField("Delimiter", BindingFlags.Public | BindingFlags.Static).SetValue(null, '-');
Func<char> getDelimiter = () => Type.Delimiter;
Console.WriteLine( getDelimiter() );

此代码可靠地为我显示了该字段的更新值。我不能说我非常惊讶;该字段被声明为只读,因此 JITter 可以在访问该字段时使用该假设。你正在做一些顽皮和邪恶的事情,真的不应该期望它以一种理智的方式工作。

现在,至于为什么在修改 bool.TrueString 字段时没有显示出来,我最好的猜测是这是因为 bool.TrueString 是一个引用类型 (string) 而 Type.Delimiter 是值类型 (char)。我可以想象这会触发不同的优化。

我确实看过这段代码的反汇编:

        Console.WriteLine( bool.TrueString );
006F2E53 8B 0D B8 10 40 03 mov ecx,dword ptr ds:[34010B8h]
006F2E59 E8 52 A6 77 54 call 54E6D4B0

Console.WriteLine(Type.Delimiter);
006F2E5E B9 2E 00 00 00 mov ecx,2Eh
006F2E63 E8 B0 FA E0 54 call 55502918

您可以非常清楚地看到,JITter 通过将其替换为文字值 '.' 优化了 Type.Delimiter 字段访问。 bool.TrueString 的静态字段访问似乎仍然从实际字段加载。

关于c# - 为什么我不能使用反射更改 Type.Delimiter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38859596/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com