C# 非虚拟方法和密封方法之间有什么区别?

C# 非虚拟方法和密封方法之间有什么区别?,c#,C#,我想解决一个困惑。。在C#中,只有带有virtual标记的基类方法才能在派生类中重写。不能重写没有virtual标记的基类方法。派生类最多可以使用new隐藏基类方法。然后我们有密封的方法,这些方法也不能在基类中重写 那么,密封方法和标准非虚拟方法之间有什么区别呢 另一个相关问题。基类sealed方法是否可以在派生类中使用new替换?sealed防止对链上的虚拟方法进行任何进一步重写。您只能在覆盖的方法上定义sealed。查看密封的文档: 它们给出了密封使用的一个很好的例子: using Syst

我想解决一个困惑。。在C#中,只有带有
virtual
标记的基类方法才能在派生类中重写。不能重写没有
virtual
标记的基类方法。派生类最多可以使用
new
隐藏基类方法。然后我们有
密封的
方法,这些方法也不能在基类中重写

那么,密封方法和标准非虚拟方法之间有什么区别呢


另一个相关问题。基类
sealed
方法是否可以在派生类中使用
new
替换?

sealed
防止对链上的虚拟方法进行任何进一步重写。您只能在覆盖的方法上定义
sealed
。查看密封的
文档

它们给出了密封使用的一个很好的例子:

using System;
class A
{
   public virtual void F() {
      Console.WriteLine("A.F");
   }
   public virtual void G() {
      Console.WriteLine("A.G");
   }
}
class B: A
{
   sealed override public void F() {
      Console.WriteLine("B.F");
   } 
   override public void G() {
      Console.WriteLine("B.G");
   } 
}
class C: B
{
   override public void G() {
      Console.WriteLine("C.G");
   } 
}

在这种情况下,从
B
派生的任何人都可以覆盖
G
,但不能覆盖
F

,如果我读取正确,sealed允许停止虚拟。基本上撤消虚拟。

密封的方法只能是重写基类中的方法的方法,因此不可能进一步重写

从文档中:

当实例方法声明包含密封修饰符时 方法称为密封方法。
如果一个实例方法 声明包括密封修饰符,它还必须包括 覆盖修改器


虚拟方法不需要这样做。

原始海报提出了两个不同的问题:

  • 密封的
    方法和标准的非虚拟方法有什么区别
  • 基类
    密封的
    方法是否可以在派生类中使用
    new
    替换
  • 问题1-密封方法和非虚拟方法之间的区别 如果您不希望子类能够访问正在添加的新方法,那么创建非虚拟方法是理想的解决方案。例如,您可以向不在其父类中的类添加非虚拟方法

    但是,有时类的父类将方法定义为
    virtual
    ,但您不希望类的任何子类能够重写此方法的特定
    override
    。这是当您使用密封的
    时。它告诉编译器once
    virtual
    方法不能再被重写。请参阅
    密封的
    上的文档

    问题2-是否可以使用
    new
    是的,他们可以,尽管这可能不符合你的想法。替换
    密封的
    方法意味着调用该方法将调用您的实现。但是,如果您的类被强制转换为对父类的引用,则将使用父类的方法实现,而不是您的方法实现。微软文档解释了这一点

    下面的示例是从Microsoft的文档中稍微修改的:

    public class A
    {
        public virtual void DoWork() { Console.WriteLine("A"); }
    }
    
    public class B : A
    {
        public override void DoWork() { Console.WriteLine("B"); }
    }
    
    public class C : B
    {
        public sealed override void DoWork() { Console.WriteLine("C"); }
    }
    
    public class D : C
    {
        // Uncommenting the following line would cause a compilation error, since DoWork is sealed
        // public override void DoWork() { Console.WriteLine("D"); }
        
        public new void DoWork() {  Console.WriteLine("D"); }
    }
    
    ...
    
    // Later on in a class
    D d = new D();
    d.DoWork(); // Prints "D"
    
    C c = d;
    c.DoWork(); // Prints "C"
    

    隐马尔可夫模型。。这是C#spec中的
    sealed
    示例。但是非虚拟方法和差异解释在哪里呢?因此
    sealed
    在某种程度上,使
    virtual
    函数,
    非虚拟
    ,在下面的某个地方?我的意思是,
    sealed
    删除方法的
    virtual
    分类?@Ahmad
    sealed
    表示此方法已被最后一次重写,如果您派生,则无法再次重写。因此,我上面所说的是正确的,对吗?因此我正确地理解了它。事实上,尝试将
    sealed
    应用于没有
    override
    的方法会出现编译时错误CS0238:“FullMethodName”无法密封,因为它不是一个override。sealed关键字和Virtual关键字不起相同的作用。可以在虚拟方法上定义密封方法最后一个问题:
    new
    修饰符不能替换任何内容。它只是告诉编译器,当您在类中引入一个新成员时,如果该成员的名称(加上方法的签名)与已经存在的(继承的)成员相同,就不要再抱怨了。什么都没有被取代。两种方法(成员)都存在,但并不相关。其中一个方法在某些上下文中是隐藏的,但仍然可以通过强制转换对基类型的引用来找到(并调用)它。避免使用
    new
    修饰符;相反,请为新方法选择一个未使用的名称。这不是真的。方法仍然是虚拟的,vtable将仅限于那些条目,直到方法被密封为止。这是一个重要的区别。@Servy,对,这正是我的意思。将虚拟方法标记为密封的继承链上的类本质上阻止了将从它继承的类将方法视为虚拟的(即使它最初是虚拟的)。换句话说,sealed关键字将删除先前的虚拟关键字(在该级别,而不是在以下级别。仅在该级别和更高级别)。