如何在 C# 中隐藏(删除)基类的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1125746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 08:48:39  来源:igfitidea点击:

How to hide (remove) a base class's methods in C#?

c#inheritancelanguage-featuresinheritance-prevention

提问by Ogre Psalm33

The essence of the problem is, given a class hierarchy like this:

问题的本质是,给定一个这样的类层次结构:

class A
{
    protected void MethodToExpose()
    {}

    protected void MethodToHide(object param)
    {}
}

class B : A
{
    new private void MethodToHide(object param)
    {}

    protected void NewMethodInB()
    {}
}

class C : B
{
    public void DoSomething()
    {
        base.MethodToHide("the parameter"); // This still calls A.MethodToHide()
        base.MethodToExpose(); // This calls A.MethodToExpose(), but that's ok
        base.NewMethodInB();
    }
}

How can I prevent any classes that inherit from class "B" from seeing the method A.MethodToHide()? In C++, this was easy enough by using a declaration such as class B : private A, but this syntax is not valid in C#.

如何防止从“B”类继承的任何类看到该方法A.MethodToHide()?在 C++ 中,这很容易通过使用诸如 的声明class B : private A,但此语法在 C# 中无效。

For those interested (or wondering what I'm reallytrying to do), what we're trying to do is create a wrapper for for Rhino.Commons.NHRepository that hides the methods we don't want to expose to our group of developers, so we can have a cookie-cutter way of developing our app that new developers can easily follow. So yes, I believe the "Is-A" test is valid for the whole chain (WidgetRepository Is-A BaseRepository Is-A NHRepository).

对于那些感兴趣的人(或想知道我真正想做的是什么),我们要做的是为 Rhino.Commons.NHRepository 创建一个包装器,以隐藏我们不想向我们的开发人员组公开的方法,因此我们可以采用千篇一律的方式来开发新开发人员可以轻松遵循的应用程序。所以是的,我相信“Is-A”测试对整个链(WidgetRepository Is-A BaseRepository Is-A NHRepository)都是有效的。

Edit: I should have mentioned, for the sake of argument, that class A is an API class outside of our control. Otherwise the problem gets considerably easier.

编辑:为了论证,我应该提到类 A 是我们无法控制的 API 类。否则问题会变得容易得多。

采纳答案by Michael Meadows

You can't do it and preserve the hierarchy. If possible, you should create interfaces that define your ideal, then subclass the bases classes and implement the interfaces. reference the interfaces only (not the base class types) in your code.

你不能这样做并保留层次结构。如果可能,您应该创建定义您的理想的接口,然后子类化基类并实现接口。在您的代码中仅引用接口(而不是基类类型)。

The Adapter patternwas created specifically to solve the problem of how to use a framework when its API doesn't line up exactly with your needs.

适配器模式是专为解决如何使用框架的问题,当它的API不符合您的需求正好排队。

回答by Blixt

If you want to custom tailor a set of features, I'd say you want to make a wrapper rather than inherit the functionality. I don't know of a way to do what you want in C# either.

如果您想定制一组功能,我会说您想制作一个包装器而不是继承功能。我也不知道有什么方法可以在 C# 中做你想做的事。

Think about it, what if some code outside your control wants this NHRepositoryinstance for something... but you've removed the functionality from the function it needs in your child class (which you would send in, since that's your only NHRepositoryinstance.) Everything goes boom. That's why I don't think it's even possible to do without some ugly hack.

想一想,如果您控制之外的某些代码想要此NHRepository实例用于某些事情,该怎么办……但是您已经从它在您的子类中需要的函数中删除了该功能(您将发送它,因为那是您唯一的NHRepository实例。)一切去繁荣。这就是为什么我认为没有一些丑陋的黑客是不可能的。

回答by James

Your code in derived class B won't hide the base method from all derived types, only itself. You would have to set the method to private in the base. The only way around this issue is to create another base class that does not expose this method.

您在派生类 B 中的代码不会对所有派生类型隐藏基方法,只会隐藏其自身。您必须在基础中将该方法设置为私有。解决此问题的唯一方法是创建另一个不公开此方法的基类。

回答by LBushkin

C# does not have a concept similar to protected or private inheritance in C++.

C# 没有类似于 C++ 中受保护或私有继承的概念。

Your best option is to aggregate an instance of the class and expose the set of methods you are interested in you consumers having access to.

您最好的选择是聚合类的一个实例,并公开您感兴趣的消费者可以访问的一组方法。

Although in your case I don't think it's possible, you could look into creating an interface that exposes just the common functionality that you want consumers be work with so that your wrapper can be substitutable in some instances for it's aggregate.

尽管在您的情况下,我认为这是不可能的,但您可以考虑创建一个接口,该接口仅公开您希望消费者使用的通用功能,以便您的包装器在某些情况下可以替代它的聚合。

回答by Frank V

I never knew you could do that in C++ though I don't know much about C++. I'm afraid that I agree with Blixt that a wrapper classis probably how I'd implement this.

我从来不知道你可以在 C++ 中做到这一点,尽管我对 C++ 了解不多。恐怕我同意 Blixt 的观点,即包装类可能是我实现这一点的方式。

It might work (but I'm not sure) to simply override the functionand throw an exception upon a call....

它可能会工作(但我不确定)简单地覆盖该函数并在调用时抛出异常......

回答by Jake Pearson

If you are using Visual Studio, you can hide the methods/properties from intelliprompt with this attribute:

如果您使用的是 Visual Studio,则可以使用此属性从智能提示中隐藏方法/属性:

class A
{
    protected void MethodToExpose()
    {}

    [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
    protected void MethodToHide(object param)
    {}
}

It won't actually get rid of the function, but if they are just your internal people. It might be close enough.

它实际上不会摆脱该功能,但如果他们只是您的内部人员。它可能足够接近。

回答by Fredrik M?rk

As far as I know you can't hide it in the way you want. I think you could prevent it from being used in any practical manner though:

据我所知,你不能以你想要的方式隐藏它。我认为您可以防止以任何实际方式使用它:

class B : A
{
    public new void MethodToHide(object param)
    { 
        throw new DontUseThisMethodException();
    }

    protected void NewMethodInB()
    {}
}

Not the nicest thing to do though, so you would probably want to solve it in some other way...

不过这不是最好的事情,所以你可能想以其他方式解决它......

回答by KDogg

Actually you CAN hide A's method from C if you would have defined B's method as accessible from C.

实际上,如果您将 B 的方法定义为可从 C 访问,则您可以对 C 隐藏 A 的方法。

The only problem with your code is that you use "private" on your hiding declaration... if you use protected or public you would not have any issues and it would operate as you expect. I do this all the time with fields.

您的代码的唯一问题是您在隐藏声明中使用了“private”……如果您使用 protected 或 public,您将不会有任何问题,并且它会按您的预期运行。我一直在用字段这样做。

回答by Monkey Code

Obsolete It

过时了

In class B, override MethodToHide and add the Obsolete attribute

在 B 类中,覆盖 MethodToHide 并添加 Obsolete 属性

[Obsolete("Reason", true)] // true will cause a compile-time error

Set EditorBrowsable

设置 EditorBrowsable

(As mentioned previously)

(如前所述)

In class B, override MethodToHide and add the EditorBrowsable attribute

在 B 类中,覆盖 MethodToHide 并添加 EditorBrowsable 属性

[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]

Throw exception

抛出异常

(As mentioned previously)

(如前所述)

In class B, override MethodToHide and throw exception.

在 B 类中,重写 MethodToHide 并抛出异常。

Create Wrapper

创建包装器

I think Michael Meadows is right. Use the Adapter pattern. This pattern also allows easier mocking of code when unit testing.

我认为迈克尔梅多斯是对的。使用适配器模式。这种模式还允许在单元测试时更轻松地模拟代码。

class B: IInterface
{    
    protected void MethodToExpose()
    {
        A a = new A();
        a.MethodToExpose();
    }

    protected void NewMethodInB()
    {
    }
}

回答by Guy Levin

In my opinion, the best way to do it, if you just want to hide and not really override and externalize a new functionallity, is just to add an EditorBrowsableState attribute. It hides the the method in the visual studio editor. Who ever will try to use it will end up with a compile time error.

在我看来,如果您只想隐藏而不是真正覆盖和外部化新功能,最好的方法就是添加 EditorBrowsableState 属性。它隐藏了 Visual Studio 编辑器中的方法。谁会尝试使用它最终会出现编译时错误。

Just add this code on top of your method:

只需将此代码添加到您的方法之上:

[System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]

For example

例如

public class User
{        
    public void DoSomething()
    {
       Something...
    }
}

public class Manager
{
    [System.ComponentModel.EditorBrowsable(EditorBrowsableState.Never)]
    public override void DoSomething()
    { }
}

void main()
{
   User user = new User();
   user.DoSomething();

   Manager manager = new Manager();
   manager.DoSomething(); // --------- This row will throw a design time error
}

Good Luck :)

祝你好运 :)