Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.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#_Inheritance - Fatal编程技术网

C#防止基类方法被派生类中的新修饰符隐藏

C#防止基类方法被派生类中的新修饰符隐藏,c#,inheritance,C#,Inheritance,这是我的情况。在Java中,我可以在基类/超类中将一个方法标记为final,派生类无法屏蔽具有相同签名的方法。然而,在C#中,new关键字允许继承我的类的人创建具有相同签名的方法 请参见下面的示例。我需要公开orignal.MyClass,所以请不要建议将其作为答案。从Java到C,这似乎是一个丢失的特性# 编辑:不是重复的 所有的答案似乎都表明,不可能防止方法在派生类中被隐藏/隐藏。这在将一些旧Java代码迁移到C#时变得显而易见。Java中的最后一个方法不允许任何人在任何派生类中使用相同的方

这是我的情况。在Java中,我可以在基类/超类中将一个方法标记为final,派生类无法屏蔽具有相同签名的方法。然而,在C#中,new关键字允许继承我的类的人创建具有相同签名的方法

请参见下面的示例。我需要公开orignal.MyClass,所以请不要建议将其作为答案。从Java到C,这似乎是一个丢失的特性#

编辑:不是重复的

所有的答案似乎都表明,不可能防止方法在派生类中被隐藏/隐藏。这在将一些旧Java代码迁移到C#时变得显而易见。Java中的最后一个方法不允许任何人在任何派生类中使用相同的方法签名。虽然在大多数情况下,C#允许派生类中具有相同签名的方法是很好的,但如果有必要的话,防止这种行为会很好

//如何预防以下情况

这是无法避免的。这是语言允许的

请注意,在实践中,这很少重要。如果希望基类用作类,则仍将调用方法。使用
new
仅在对声明为
DerivedClass
的变量使用
DerivedClass
时隐藏方法

这意味着,如果围绕
MyClass
构建API,当实例被传递到方法中时,它仍然会调用
MyMethod


根据评论进行编辑:

如果您担心有人将您的类划分为子类,那么您唯一的实际选择就是封闭您的类:

public sealed class MyClass
{

这将阻止人们完全创建子类。但是,如果您希望允许用户从您的类派生,则无法阻止他们将您的方法隐藏在他们的类中。

您无法阻止对公共方法或属性进行屏蔽,但您为什么要这样做?任何扩展基类的人都会故意这样做(即,他们需要键入
new
),因此他们打算这么做,为什么要尝试阻止他们呢


也许你需要改变一下你的模式?如果扩展器必须使用您的基本方法,那么您可以在其中放入一些关键的内容,从而迫使他们调用它。当然,如果做得不正确,这会很难闻,因此如果使用这种方法,则将方法标记为
virtual
,然后在文档(或方法标题注释)中提到必须调用基本方法。通过这种方式,您可以避免扩展器必须隐藏/屏蔽您的方法(尽管他们仍然可以),但如果他们愿意,他们仍然可以对其进行扩展。

我假设您确实希望防止有人重写该方法-无法阻止使用
new
隐藏方法,但它不会对基类造成风险,所以这不应该是个问题


在C#中,默认情况下方法不可重写。因此,您可以简单地通过不将基本方法标记为
virtual
abstract
来防止某人重写它。在Java中,默认情况下方法是虚拟的,因此必须使用
final
密封方法以防止重写。

我认为唯一的方法是创建接口,将方法定义放入其中,然后让原始类实现接口并显式实现方法:

    interface IAnimal
    {
        string diary(string notes, int sleephours);   
    }

    class Dogs:IAnimal
    {        

virtual public string voice()
        {
            string v = "Hao Hao"; return v;
        } 
        string IAnimal.diary(string notes,int sleephours)
        {
            return notes + sleep.ToString() + " hours";
        }

    }

    class Cats:Dogs
    {
        public override string voice()
        {
            string v = "Miao Miao"; return v;
        }
    }

您不会通过Cats实例使用diary()方法。

可能重复@Reed提到的…,
这几乎不重要
。您的代码仍将调用原始方法,而不是重复的方法。我不是要一个同等的。我建议这个用例不存在一个。我做了一个编辑。使用my api的人(比如Alice)很容易创建一个具有相同名称的类的包装器,如果这个包装器被其他人使用,它将允许Alice重新定义MyMethod()的行为并可能愚弄一个毫无防备的结局-developer@JAson不是真的-开发人员必须包含其他人的名称空间而不是您的名称空间,或者完全限定类型。不管怎样,他们都必须知道自己在做什么。@JAson,这是超越,而不是隐藏。隐藏方法对基类没有影响。@JAson您的情况的前提是有人运行来自不受信任的恶意源的代码。在这种情况下,你已经输了。正确的发展并不是一开始就把自己放在那个位置。@JAson好吧,不管是否合理,这就是行为,它不会改变(这将是一个太多的破坏性的改变,无法实现)。所以真的没什么可说的了。如果它困扰你,就不要这样做,并接受这样一个事实,即其他人可以这样做,如果他们愿意的话。问题似乎很清楚,这是关于新的关键字,而不是阻止重写……注意,在C#中,你也可以将一个方法标记为
sealed
,它的功能实际上与java中的
final
完全相同。实际上,您可以密封一个虚拟方法。也就是说,有一个虚拟方法被派生类覆盖,但有它密封它以防止进一步的重新定义。@JAson您当然可以在基类中密封一个方法。您完全可以防止它被重写,但您永远无法防止它被使用new进行跟踪,正如其他人告诉您的那样。这只是事实。@Jason-除非您将方法标记为虚拟或非虚拟,否则默认情况下方法是密封的abstract@Servy/斯坦利:明白了,你是对的。不同的是,您可以用一个新的修饰符隐藏/隐藏一个密封的方法,这在Javaland中是不可能的。我猜你必须接受它。
    interface IAnimal
    {
        string diary(string notes, int sleephours);   
    }

    class Dogs:IAnimal
    {        

virtual public string voice()
        {
            string v = "Hao Hao"; return v;
        } 
        string IAnimal.diary(string notes,int sleephours)
        {
            return notes + sleep.ToString() + " hours";
        }

    }

    class Cats:Dogs
    {
        public override string voice()
        {
            string v = "Miao Miao"; return v;
        }
    }