为什么不把一切都变成"虚拟"?

Mat*_*att 18 .net c# virtual overriding

可能重复:
为什么C#默认将方法实现为非虚方式?

我主要讲的是C#,.NET 3.5,但总体上想知道不考虑所有"虚拟"的好处是什么 - 也就是说在子类实例中调用的方法总是执行最多的子版本那种方法.在C#中,如果父方法未使用"虚拟"修饰符标记,则情况并非如此.例:

public class Parent
{
    public void NonVirtual() { Console.WriteLine("Non-Virtual Parent"); }
    public virtual void Virtual(){ Console.WriteLine("Virtual Parent"); }
}

public class Child : Parent
{
    public new void NonVirtual() { Console.WriteLine("Non-Virtual Child"); }
    public override void Virtual() { Console.WriteLine("Virtual Child"); }
}

public class Program
{
    public static void Main(string[] args)
    {
        Child child = new Child();
        Parent parent = new Child();
        var anon = new Child();

        child.NonVirtual();           // => Child
        parent.NonVirtual();          // => Parent
        anon.NonVirtual();            // => Child
        ((Parent)child).NonVirtual(); // => Parent

        child.Virtual();              // => Child
        parent.Virtual();             // => Child
        anon.Virtual();               // => Child
        ((Parent)child).Virtual();    // => Child
    }
}
Run Code Online (Sandbox Code Playgroud)

上面观察到的非虚拟行为的好处究竟是什么?我唯一能想到的是"如果父母的作者不希望他的方法是虚拟的怎么办?" 但后来我意识到我无法想到一个好的用例.有人可能会争辩说,类的行为取决于非虚方法如何操作 - 但在我看来,有一些不良的封装正在进行,或者该方法应该被密封.

沿着这些方向,似乎"隐藏"通常是一个坏主意.毕竟,如果创建了一个Child对象和方法,那么它似乎是出于特定原因而覆盖Parent.如果儿童器械(和隐藏的父母)非虚(),它是超级容易没有得到调用儿童::非虚的东西很多人可能会认为"预期"的行为().(我说"预期",因为有时很容易注意到"隐藏"正在发生).

那么,不允许一切都有"虚拟"行为有什么好处?如果很容易出现意外行为,隐藏非虚拟父级的好用例是什么?

如果有人对我为什么提出这个问题感到好奇 - 我最近正在检查Castle Projects DynamicProxy库.使用它的一个主要障碍是您要代理的任何方法(或属性)都必须是虚拟的.对于开发人员来说,这并不总是一个选择(如果我们无法控制源代码).更不用说DynamicProxy的目的是避免代理类与您尝试使用代理实现的任何行为之间的耦合(例如Logging,或者可能是Memoization实现).通过强制虚拟方法来实现这一目标,实现这一点的目的非常薄,但是将DynamicProxy与它所代表的所有类的钝连接 - 想象一下,你有很多标记为虚拟的方法,即使它们永远不会被继承和覆盖,所以任何其他看着代码的开发人员可能想知道"为什么这些甚至是虚拟的?让我们改回来".

无论如何,那里的挫败让我想知道非虚拟的好处是什么,当看起来虚拟的一切可能更清楚(IMO,我想),也许(?)有更多的好处.

编辑:标记为社区维基,因为它似乎是一个可能有主观答案的问题

Zif*_*fre 9

因为您不希望人们重写您没有设计类的方法.要确保覆盖方法或从类派生是安全的,需要付出很大的努力.virtual如果您没有考虑可能发生的情况,那么将其设为非更安全.