【问题标题】:Setting readonly fields (Is this bug?)设置只读字段(这是错误吗?)
【发布时间】:2012-08-25 10:17:09
【问题描述】:

刚玩c#的时候,发现了一件奇怪的事情。

代码如下:

class Program
{
    static void Main(string[] args)
    {
        System.Diagnostics.Debug.Write(string.Empty);

        typeof(string)
            .GetField("Empty", BindingFlags.Static | BindingFlags.Public)
            .SetValue(null, "Tolgahan");


        Console.WriteLine(string.Empty);

        // output : Tolgahan
    }
}

为什么反射让我们改变只读字段?


问题是“为什么允许通过反射进行设置”,而不是“如何做”,所以它不是 Can I change a private readonly field in C# using reflection? 的重复。

【问题讨论】:

  • 你可以用反射做各种你不能正常做的事情。例如,您可以从其他类获取/设置私有字段。我几乎可以肯定这不是错误。至于它是否可取是另一回事。
  • 窃取引用,只读是为了防止“墨菲,而不是马基雅维利”
  • @Dennis:另一个问题只是问它是否可能,这个问题说它是可能的,但问为什么(因此 IMO 比另一个问题更有价值)。
  • @O.R.Mapper:仔细看看 Eric Lippert 的评论。有一个解释。
  • 如果剩下的只是“为什么会这样”,除非 .Net 的首席设计师开会并做出统一的回应,否则我不希望有明确的答案。

标签: c# reflection readonly


【解决方案1】:

同样,化学定律说任何反应都不能导致一种元素的原子变成另一种元素的原子,但物理定律说它一直在发生。化学是物理学的一个受限制的子集,以便将问题简化为更可解决的方式。

在这种情况下,反射是物理学,而普通编程是化学。它以更简单的心态运作。反射允许您规避那组更简单的规则,让您面临新的流程,但也面临新的危险。

【讨论】:

  • 多么奇怪的比喻。不,它不是一个错误就足够了,还是太化学了?
  • 试着用 Bryan Cranston 的声音来解读它,它突然开始变得有意义了。
  • @ssg 至少比 Aaron Paul 更有意义 :-)
  • 我会和卡尔·萨根一起去的 :)
【解决方案2】:

因为readonlyprivate 一样,防范墨菲,而不是马基雅维利*。

我们使用 readonlyprivate 以及任何其他限制我们可以做的事情,主要是因为我们希望限制更多不正确、不一致或只是愚蠢的事情,而不是我们拥有有用和富有成果的事情。

但它仍然只是 1 和 0。如果某些内存设置为数字“42”并且我们通过只读字段访问它,则在创建对象时它不是只读的。没有什么能阻止它被改变,除了编译器发现“嘿,一开始你说你不想改变它,现在你试图改变它,结果是什么?这两个决定中的一个肯定是错误的”。

现在,不能保证反射能够改变它,但也不能保证它不会。现在,反射的工作方式和只读的工作方式意味着你可以改变它。至少,要阻止那些可能因为认为自己已经这样做而费心去做这件事的人,需要做很多工作(也许成本会影响我们的用户以及需要实施这项工作的团队)一个很好的理由。

请注意,与反射相关的权限确实会阻止马基雅维利,

*严格地说,墨菲在谈论我们应该如何设计东西来阻止人们不小心做一些灾难性的事情——readonly 就是一个很好的例子,不能以错误的方式插入更好的插头——还有马基雅维利是在教而不是练习技术。但是,它远不如简明扼要的说法。

【讨论】:

  • @p.s.w.g 墨菲和马基雅维利的那个?我不能要求信用。我所知道的最早的类似用法(大约在 C++ 中使用 private)是 Bjarne Stroustrup 的,虽然我不知道他是不是第一个。
【解决方案3】:

这是可能的,因为 .Net 中的反射是以这种方式实现的。我只能猜测这样做的动机,但它是一个功能强大(但速度较慢)的工具,提供了极大的灵活性和滥用的可能性。

这不是实现这种改变的唯一方式,但这种讨论与任何进一步的主观猜测一样,都是题外话,不合时宜。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 2014-12-27
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多