Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么不把一切都变成';虚拟的';?_C#_.net_Virtual_Overriding - Fatal编程技术网

C# 为什么不把一切都变成';虚拟的';?

C# 为什么不把一切都变成';虚拟的';?,c#,.net,virtual,overriding,C#,.net,Virtual,Overriding,可能重复: 我主要讲的是C#,.NET3.5,但总的来说,我想知道不考虑所有“虚拟”的好处是什么——也就是说,在子类实例中调用的方法总是执行该方法的最子版本。在C#中,如果父方法未标记“virtual”修饰符,则情况并非如此。例如: public class Parent { public void NonVirtual() { Console.WriteLine("Non-Virtual Parent"); } public virtual void Virtual(){ C

可能重复:

我主要讲的是C#,.NET3.5,但总的来说,我想知道不考虑所有“虚拟”的好处是什么——也就是说,在子类实例中调用的方法总是执行该方法的最子版本。在C#中,如果父方法未标记“virtual”修饰符,则情况并非如此。例如:

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
    }
}
上述非虚拟行为的具体好处是什么?我唯一能想到的是“如果Parent的作者不希望他的方法是虚拟的怎么办?”但后来我意识到我想不出一个好的用例来实现这一点。有人可能会说,类的行为取决于非虚拟方法的操作方式——但在我看来,似乎存在一些不良的封装,或者应该密封该方法

按照同样的思路,“隐藏”似乎通常是个坏主意。毕竟,如果创建了子对象和方法,那么这样做似乎是出于覆盖父对象的特定原因。如果子实现(并且隐藏了父)非虚拟(),则很难获得许多可能调用调用子:“非虚拟”()的“预期”行为。(我说“预期”是因为有时很容易不注意到“隐藏”正在发生)

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

如果有人对我为什么提出这个问题感到好奇的话——我最近正在研究Castle项目DynamicProxy图书馆。使用它的一个主要障碍是,要代理的任何方法(或属性)都必须是虚拟的。对于开发人员来说,这并不总是一个选项(如果我们不能控制源代码的话)。更不用说DynamicProxy的目的是避免代理类与您试图通过代理实现的任何行为(例如日志记录,或者可能是备忘录实现)之间的耦合。通过强制虚拟方法来实现这一点,实现的是DynamicProxy与它代理的所有类的非常稀疏但迟钝的耦合-想象一下,您有大量标记为virtual的方法,即使它们从未被继承和重写,所以任何其他查看代码的开发人员都可能会感到奇怪“为什么这些都是虚拟的?让我们把它们换回来。”

不管怎么说,那里的挫折感让我想知道非虚拟的好处是什么,而虚拟的一切似乎更清晰(我想是这样),也许(?)有更多的好处


编辑:标记为community wiki,因为这似乎是一个可能有主观答案的问题

非虚拟方法的一个关键好处是它可以在编译时绑定。也就是说,编译器可以确定在代码中使用方法时调用哪个实际方法


如果将要调用的实际方法声明为虚拟方法,则在编译时无法知道该方法,因为引用实际上可能指向已重写它的子类型。因此,当需要解析要调用的实际方法时,运行时会有一点开销。

在许多情况下,类正确运行是至关重要的至少,给定的方法具有特定的行为。如果该方法在继承的类中被重写,则无法保证该方法将正确实现预期的行为。如果您的类专门为继承而设计,并且将支持具有不同实现的方法,则只应将该方法标记为虚拟。为inh设计继承并不容易,在许多情况下,错误地重写方法会破坏类的内部行为。在框架中,可以调用非虚拟成员并具有一系列预期输出,如果方法是虚拟的,则该方法的结果可能是未测试的预期结果。允许方法是非虚拟的-虚拟为框架操作提供预期的结果。

简单:类中的整个要点是封装某种抽象。例如,我们需要一个行为类似于文本字符串的对象

现在,如果一切都是虚拟的,我就能做到:

class MessedUpString : String{
   override void Trim() { throw new Exception(); }
}
然后将其传递给某个需要字符串的函数。当他们试图修剪该字符串时,它就会爆炸

字符串不再像字符串一样工作。这是一件好事吗

如果一切都是虚拟的,你将很难强制执行类不变量。你允许类抽象被破坏

默认情况下,一个类应该封装它应该遵循的规则和行为。原则上,你所做的一切都是一个可扩展性挂钩,函数可以被更改为做任何事情。只有在少数情况下,当我们的行为实际上是用户定义的时候,这才有意义

类之所以有用,是因为它们允许我们忽略实现细节。我们可以简单地说:“这是一个字符串对象,我知道它将表现为字符串。我知道它永远不会违反这些保证中的任何一个”。如果不能维护该保证,则该类是无用的。您不妨将所有数据成员公开,并将成员方法移到该类之外

你知道那条路吗?
在任何需要基类B的对象的地方,您都应该能够传递派生类D的对象。这是面向对象编程的最基本规则之一。我们需要知道,当我们将派生类向上转换到基类并将其传递到需要基类的函数时,派生类仍然可以工作。这意味着我们必须使某些行为固定且不可更改。

因为您不希望人们重写未为其设计类的方法。要确保重写方法或甚至从