Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.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中重写方法#_C#_C# 4.0_Sealed - Fatal编程技术网

C# 防止在C中重写方法#

C# 防止在C中重写方法#,c#,c#-4.0,sealed,C#,C# 4.0,Sealed,如何防止在派生类中重写方法 在Java中,我可以通过在我希望防止被重写的方法上使用final修饰符来实现这一点 如何在C#中实现同样的效果? 我知道使用sealed,但显然我只能使用override关键字 class A { public void methodA() { // Code. } public virtual void methodB() { // Code. } } class B : A {

如何防止在派生类中重写方法

在Java中,我可以通过在我希望防止被重写的方法上使用
final
修饰符来实现这一点

如何在C#中实现同样的效果?
我知道使用
sealed
,但显然我只能使用
override
关键字

class A
{
    public void methodA()
    {
        // Code.
    }

    public virtual void methodB()
    {
        // Code.
    }
}

class B : A
{
    sealed override public void methodB()
    {
        // Code.
    } 
}
因此,在上面的示例中,我可以防止
methodB()
被从class
B
派生的任何类重写,但是我首先如何防止class
B
重写
methodB()


更新:当我发布这个问题时,我错过了类A的
methodB()
声明中的
virtual
关键字。已更正。

如您所述,您可以通过使用
sealed
override

class B : A
{
    public sealed override void methodB()
    {
        Console.WriteLine("Class C cannot override this method now");
    }
}
使用
密封的
修饰符以及
重写
可以防止派生类进一步重写该方法

如果不希望类A中的
methodB
被任何子类重写,请不要将该方法标记为“虚拟”。只需将其移除即可。virtual关键字允许在子类中重写该方法

public void methodA()
{       
}

在类上使用
sealed
关键字,以防止进一步重写该类

您无需执行任何操作。
virtual
修饰符指定可以重写方法。省略它意味着该方法是“最终的”

具体来说,方法必须是
virtual
abstract
override
才能被重写


使用
new
关键字将允许隐藏基类方法,但它仍然不会覆盖它,即当您调用
A.methodB()
时,您将获得基类版本,但如果调用
B.methodB()
则将获得新版本。

在基类中,sealed关键字仅用于防止派生类,但在继承类中,它可用于防止另一个继承类重写该方法

为了防止基类方法被重写,只需不将其指定为虚拟。在您提供的示例中,类B无法重写
methodB
,因为
methodB
未在原始类上标记为虚拟

这将汇编:

class A
{
    public virtual void methodA()
    {
        //code
    }
    public virtual void methodB()
    {
        //code
    }
}
class B:A
{
    public override void methodB()
    {
        //code
    } 
}
这不会:

class A
{
    public void methodA()
    {
        //code
    }
    public void methodB()
    {
        //code
    }
}
class B:A
{
    public override void methodB()
    {
        //code
    } 
}
编辑:澄清并更正了我关于C#中sealed关键字

的原始陈述,一个未标记为
virtual
(还包括虚拟函数的重写)的函数被有效地密封,不能被重写。因此,您的示例代码实际上不会编译,因为override关键字无效,除非基类中有一个标记为virtual的方法具有相同的签名

如果A.methodB()被标记为virtual,那么您可以从A重写该方法,但可以使用
sealed
关键字,防止在派生更间接的类中进一步重写该方法

需要记住的一点是,虽然可以防止方法重写,但方法隐藏却不能。鉴于您目前对A类的定义,以下B类定义是合法的,您对此无能为力:

class B:A
 {
      public new void methodB()
            {
                    //code
            } 
  }
new
关键字基本上“打破”了继承/覆盖层次结构,因为它属于这一方法;对类B的任何引用,如果被视为类B(或任何进一步的派生类型),都将使用类B的实现,而忽略类a的实现,除非B的实现专门调用它。但是,如果要将类B的实例视为类a(通过强制转换或将其作为参数传递),则“新”实现将被忽略


这与重写不同,在重写中,被视为类a并真正重写虚拟方法B的类B仍将使用类B对方法的重写。还要理解方法隐藏是推断出来的(尽管您会得到编译器警告);如果在派生类中声明具有相同签名的方法,并且未指定new或override,基类方法将被隐藏。

这是C#4中用于密封方法的新功能吗?如果您尚未重写该方法,则不要使用
virtual
对其进行修饰,则不会考虑对您的类型进行方法绑定。我相信类a中的方法应该是
virtual
如果你打算推翻它们。@UweKeim-不,它已经存在一段时间了@CAbbott-我的错误。。我更新了代码以反映同样的情况。使用sealed修饰符可以防止类从
类a
派生。这不是要求的。@KendallFrey:这个问题的标题让我觉得它是关于防止进一步的覆盖。Thanks@KendallFrey
sealed
可以应用于方法,只要它们也是重写。它防止在派生类中进一步重写(正如Shyju指出的那样)。
sealed
确实可以用于单个方法,只是
sealed
不能用于方法的最高级别实现;它必须在重写基本实现的方法上使用,在进一步派生时,基本上从更高的继承级别否定“virtual”关键字。所以,你错了,它不能被使用,但它不能解决他的问题anyway@KeithS谢谢你。我以前从未见过它用于密封和覆盖方法,但感谢您教会我一些新的东西。我已经适当地编辑了我的答案,在
new
修改器上有很好的信息。我甚至不知道这一点。在一种允许显式表达这么多内容的语言中,这是令人沮丧的,没有一个关键字可以显式地说“这并不意味着永远都会被覆盖”,只要你不意外地在以后将其虚拟化就好了