gpt4 book ai didi

c# - 为什么私有(private)虚拟方法在 C# 中是非法的?

转载 作者:IT王子 更新时间:2023-10-29 03:58:36 26 4
gpt4 key购买 nike

来自 C++ 背景,这让我感到惊讶。在 C++ 中,将虚函数设为私有(private)是一种很好的做法。来自 http://www.gotw.ca/publications/mill18.htm :“指南#2:更喜欢将虚拟函数设为私有(private)。”
我还引用了 Eric Lippert 的博客,来自 Knights-knaves-protected-and-internal :

Private virtual methods are illegal in C#, which irks me to no end. Iwould totally use that feature if we had it.


我知道在 C# 中,您将无法覆盖派生(但不是嵌套)类中的私有(private)虚拟方法。为什么会这样?在 C++ 中,访问说明符与您是否可以覆盖函数无关。

最佳答案

我注意到这里有两个问题。将来您可能会考虑发布两个问题,而不是将两个问题合二为一。当您将这样的问题结合起来时,通常只会出现第一个问题的答案。

第一个问题是“为什么私有(private)虚拟方法在 C# 中是非法的?”

以下是反对“私有(private)虚拟方法”功能的论据:

  • private virtual 仅在您具有嵌套派生类时才有用。这是一种有用的模式,但远不如非嵌套派生类情况常见。
  • 如果您希望限制在非嵌套​​派生类中覆盖方法的能力,那么您可以通过限制非嵌套类从基类派生的能力来实现;将所有基类构造函数设为私有(private)。因此,不需要私有(private)虚拟来防止覆盖; protected virtual 就足够了,因为只会嵌套派生类。
  • 如果您希望限制在非嵌套​​派生类中调用方法的能力,那么您可以将该方法设为内部虚拟,然后告诉您的同事不要使用该方法。编译器不强制执行这一点很令人恼火,但是编译器也没有对应该如何使用方法强制执行任何其他语义约束;获得正确的语义是你的事,而不是编译器的事,你必须通过适当的代码审查来强制执行。因此,不需要私有(private)虚拟来阻止调用;内部虚拟加上代码审查就足够了。
  • 可以使用现有部件实现此模式:
    abstract class C
    {
    private int CF() { whatever; }
    private Func<int> f;
    public C() { f = CF; }
    private int F() { return f(); }
    private class D : C
    {
    private int DF() { whatever; }
    public D() { f = DF; }
    }

    现在我有一个方法 F,它实际上是虚拟的,但只能被派生的嵌套类“覆盖”。

  • 由于在每种情况下 protected 、内部或 protected 内部都可以解决问题,因此不需要私有(private)虚拟。这几乎从来都不是正确的做法,因为您必须已经 promise 使用嵌套派生类模式。因此,该语言使其成为非法。

    的论据是:

    在实际代码中,有时我希望虚拟方法成为类的私有(private)实现细节,我希望通过非嵌套内部类和嵌套内部类来扩展该类。必须强制执行不由我的同事调用内部方法的不变性是令人烦恼的;我希望编译器能够强制执行这一点,而不必像制作委托(delegate)类型的字段等那样疯狂地跳槽。

    此外,还有简单的一致性和正交性问题。两个应该独立的东西——可访问性和虚拟性——却不必要地相互影响,这似乎很奇怪。

    反对该功能的论据非常强烈。的论据非常薄弱。因此,没有这样的功能。我个人非常喜欢它,但我完全理解为什么设计团队从未接受过我。这不值得付出代价,而且我不想发布更好的功能,因为我们将预算花在了一项几乎没有人受益的功能上。

    第二个问题是“为什么在 C# 中不能覆盖派生的非嵌套类中的私有(private)虚拟方法?”

    有几个原因。
  • 因为你只能覆盖你能看到的。私有(private)方法是基类的私有(private)实现细节,不能访问。
  • 因为允许这样做会带来严重的安全隐患。请记住,在 C++ 中,您几乎总是一次将代码编译到应用程序中。你拥有一切的源代码;大多数时候,从 C++ 的角度来看,一切本质上都是“内部的”。在 C# 中,情况完全不是这样。第三方程序集可以轻松地从库中获取公共(public)类型,并为这些类生成新的扩展,然后可以无缝地代替基类的实例使用这些扩展。由于虚方法有效地改变了类的行为,任何出于安全原因依赖于该类不变量的代码都需要仔细设计,以便它们不依赖于基类保证的不变量。限制虚拟方法的可访问性有助于确保维护这些方法的不变量。
  • 因为允许它提供了另一种形式的脆弱基类问题。 C# 经过精心设计,与其他 OO 语言相比,不易受到脆弱基类问题的影响。如果一个不可访问的虚方法可以在派生类中被覆盖,那么基类的私有(private)实现细节如果被改变就会变成一个破坏性的变化。基类的提供者应该可以自由地改变它们的内部细节,而不必担心他们破坏了依赖于它们的派生类;理想情况下,当实现细节发生变化时,只需要维护一个类型的公共(public)、记录的接口(interface)。
  • 关于c# - 为什么私有(private)虚拟方法在 C# 中是非法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3082310/

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