【问题标题】:Why can't I change the value of String.Empty?为什么我不能更改 String.Empty 的值?
【发布时间】:2013-11-13 21:02:39
【问题描述】:

虽然我知道更改 String.Empty 的值是个坏主意,但我不明白为什么我不能这样做。

要明白我的意思,请考虑以下类:

public class SomeContext 
{ 
    static SomeContext(){}
    public static readonly string Green = "Green";
    public static readonly SomeContext Instance = new SomeContext();

    private SomeContext(){}
    public readonly string Blue = "Blue";

    public static void PrintValues()
    { 
        Console.WriteLine(new { Green, Instance.Blue, String.Empty }.ToString());
    }
}

我有一个小控制台应用程序,它试图操纵这三个只读字段。它可以成功将 Blue 和 Green 变成 Pink,但 Empty 保持不变:

        SomeContext.PrintValues();
        ///  prints out : { Green = Green, Blue = Blue, Empty = }
        typeof(SomeContext).GetField("Blue").SetValue(SomeContext.Instance, "Pink");
        typeof(SomeContext).GetField("Green", BindingFlags.Public | BindingFlags.Static).SetValue(null, "Pink");
        typeof(String).GetField("Empty", BindingFlags.Public | BindingFlags.Static).SetValue(null, "Pink");
        SomeContext.PrintValues();
        ///  prints out : { Green = Pink, Blue = Pink, Empty = }

为什么?

最初,我还问为什么String.Empty 不是一个常数。我找到了这部分问题的答案on another post 并删除了这部分问题)。

注意:没有一个“重复”对这个问题有明确的答案,这就是我问这个问题的原因。

【问题讨论】:

  • 这可能会回答这个问题:stackoverflow.com/questions/16618302/…
  • 简答:你正在改变System.String.Empty。问题是您检查 System.String.Empty 的当前值的代码已损坏,因为您违反了它的不变量。开始违反系统不变量,没有什么可以依赖。
  • 我注意到 Getvalue 返回 "Pink" 虽然访问字段返回 ""
  • How do I draw attention to old unanswered questions。如果您发现有一个问题没有得到解答,解决办法就是不要再问了。考虑在重复的帖子上设置赏金。
  • @Servy - 他们问题的意图不同。这三个都讨论了相同的基本代码行。但是,每个问题都有非常不同的原因。如果我把他们的问题改成和我的一样,我就是在歪曲他们的问题。看看它们,如果你有不同的想法,请告诉我。

标签: c# .net reflection constants immutability


【解决方案1】:

您无法更改它,因为您的机器上有 .NET 4.5。只需将项目的 Framework Target 设置更改为 3.5 即可。

CLR 具有 String.Empty 的内置知识。例如,您会看到 System.String 类从不初始化它的反射器或参考源。它在 CLR 启动期间完成。 4.5 究竟是如何防止修改可见的,有点难说。您实际上确实修改了该字段,只需添加这行代码:

  var s = typeof(String).GetField("Empty", 
             BindingFlags.Public | BindingFlags.Static).GetValue(null);
  Console.WriteLine(s);

你会看到“粉红色”。我的猜测是它被抖动拦截了。但是,我不能为此提供确凿的证据。有先例,例如尝试修改 Decimal.MaxValue,另一个只读静态值。 3.5也不改,jitter识别出来直接生成值,不用读取字段。

我刚刚发现您以完全相同的主题悬赏another question。 280Z28的帖子很相似。

【讨论】:

  • +1 - 谢谢你 - 你能建议一种方法来找到关于 JIT 优化正在发生的确凿证据吗?这在 cmets 中有一些讨论,我得到的是我需要反汇编 JIT 生成的机器代码。不幸的是,我不知道如何访问比 IL 更低级别的任何内容。我不是要求进行深入的解释,但非常感谢您朝正确的方向轻推。
  • 我完全不清楚为什么需要解决这个问题。反汇编不会让你到任何地方,你会看到抖动产生的原始地址正在使用。除了您已经知道的内容之外,它并没有告诉您更多信息,它指向一个空字符串。您将需要 v4.5 抖动源代码,除非您申请微软的工作,否则您无法获得它。
  • 汉斯,你显然是一个非常聪明的人,对软件有着深刻而普遍的理解。您是否仅通过研究具有直接实际利益的问题来获得这种理解?或者,您是否会说,您偶尔会因为了解事物的运作方式而对了解事物的运作方式产生真正的热情,并且沉迷于这种动力是达到您的专业水平的一个促成因素?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
相关资源
最近更新 更多