11

Here's my situation. In Java I can mark a method as final in the base/super class and there is no way a derived class can mask a method of the same signature. In C# however, the new keyword allows someone inheriting my class to create a method with the same signature.

See my example below. I need to keep the orignal.MyClass public so please don't suggest that as an answer. This seems to be a lost feature moving from Java to C#:

public class orignal.MyClass{
    public void MyMethod()
    {
     // Do something
    }
}

class fake.MyClass: orignal.MyClass {
    // How to prevent the following
    public new void MyMethod()
    {
     // Do something different
    }
}

EDIT: Not a duplicate.

All answers seem to suggest, it's not possible to prevent a method from being hidden/shadowed in a derived class. This became apparent while migrating some old Java code to C#. A final method in Java will not let anybody use the same method signature in any derived class. While it's great in most scenarios that C# allows a method of same signature in the derived class, it would have been great to prevent such a behavior if warranted.

codewario
  • 19,553
  • 20
  • 90
  • 159
JAson
  • 153
  • 1
  • 10

5 Answers5

12

// How to prevent the following

There is no way to prevent this. It's allowed by the language.

Note that, in practice, this rarely matters. If you expect your base class to be used as your class, your method will still be called. Using new only hides the method when using the DerivedClass from a a variable declared as DerivedClass.

This means that your API, if built around MyClass, will always still call MyMethod when instances are passed into your methods.


Edit in response to comments:

If you are worried about people subclassing your class in general, the only real option you do have would be to seal your class:

public sealed class MyClass
{

This will prevent people from creating a subclass entirely. If you want to allow people to derive from your class, however, there is no way to prevent them from hiding your method in their class.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • I made an edit. It is very easily possible for someone using my api (say Alice) to create a wrapper that has a class with the same name and then if this wrapper were to be used by another person, it will allow Alice to redefine the behavior of MyMethod() and possibly fool an unsuspecting end-developer – JAson Aug 07 '13 at 20:34
  • 1
    @JAson Not really - the developer would have to include the other person's namespace instead of yours, or fully qualify the type. Either way, they'd have to know what they're doing. – Reed Copsey Aug 07 '13 at 20:37
  • @JAson that's _overriding_, not _hiding_. Hiding a method has no impact to the base class. – D Stanley Aug 07 '13 at 20:37
  • 4
    @JAson The premise of your situation has someone running code from an untrusted malicious source. When you're in that situation you've already lost. Proper development is not putting yourself in that position to begin with. – Servy Aug 07 '13 at 20:37
  • @ReedCopsey You can mark a method as `sealed` in addition to a class to seal just that method, without sealing the whole class. It can still be shadowed though, just not overridden. – Servy Aug 07 '13 at 20:40
  • @Reed/@Servy: Agreed in principle. However the lack of a modifier similar to what final does for a java method in a base class, results in a method of same signature to be created in a derived class. Again not trying to push this into a discussion on development ethics/properness, but it seems reasonable to expect a modifier that if present in a base class method prevents any one from overriding and hiding it. – JAson Aug 07 '13 at 20:44
  • 1
    @JAson Well, reasonable or not, that's the behavior, and it's not going to change (it would be too much of a breaking change to be implemented). So there really isn't anything else to say. Don't do it if it bothers you, and live with the fact that others can do it if *they* want to. – Servy Aug 07 '13 at 20:47
  • @Servy I edited to mention sealing the class just because of the comments - the method wasn't virtual, so sealing wouldn't work (and wouldn't change the behavior in terms of this question anyways) – Reed Copsey Aug 07 '13 at 20:48
2

You can't prevent a public method or property being masked, but why would you? It takes a deliberate action from whoever extends the base class to do this (i.e. they need to type new), so they have intended to do it, why try and stop them?

Maybe you need to switch your pattern up a bit? If the extender must use your base method then you can put something critical in it, thus forcing them to call it. Of course this is smelly if not done correctly, so if you use this approach then mark your method as virtual, then in the documentation (or method header comments) mention that the base method must be called. This way you avoid the extender having to hide/mask your method (although they still could), but they can still extend it if they want.

slugster
  • 49,403
  • 14
  • 95
  • 145
0

I think the only way is to create interface the put your method definition within it, then let the original class to implement the interface and implement the method explicitly:

    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;
        }
    }

You will not use diary() method via Cats instance.

Bahaa Salaheldin
  • 515
  • 1
  • 7
  • 16
-1

I'm assuming you really want to prevent someone from overriding the method - hiding a method with new cannot be prevented, but it poses no risk to the base class, so that shouldn't be an issue.

In C# methods are not overrideable by default. So you can simply prevent someone form overriding a base method by not marking it virtual or abstract. In Java methods are virtual by default, so sealing a method by using final is necessary to prevent overriding.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • 1
    The question seems pretty clear that it is about the new keyword and not preventing overriding... – Chris Aug 07 '13 at 20:38
  • Note that in C# you can also mark a method as `sealed` which functions virtually identially to `final` in java. You can actually seal a virtual method. I.e. having a virtual method overwritten by a derived class, but having it seal it to prevent further re-definitions. – Servy Aug 07 '13 at 20:39
  • 1
    @JAson You most certainly *can* seal a method in a base class. You can absolutely prevent it from being overridden, but you can never prevent it from being shadowed using *new*, as everyone else has told you. That's just fact. – Servy Aug 07 '13 at 20:48
  • 1
    @Jason - methods are sealed _by default_ unless you mark them as _virtual_ or _abstract_ – D Stanley Aug 07 '13 at 20:49
  • @Servy/Stanley: Got it, you are right. whats different is that you can hide/shadow a sealed method with a new modifier which won't be possible in Javaland. Guess will have to live with it. – JAson Aug 07 '13 at 21:06
-1

For prevent of hiding base class method you can do like this:

public class Org
{
    public void Do()
    {
        // do something
    }
}

public class Fake : Org
{
    public new void Do()
    {
        base.Do();
        // do something
    }
}

here the base keyword refers to Father class. now you called method from Father class (here is Org) in child class and now this method doesnt hide anymore.

  • Can you please provide an explanation of how your code solves OP's problem? – codewario May 29 '22 at 16:11
  • @Bender the Greatest I'm not so professional in C# but we can call this method and it is not hidding now . but please help me to understand what is the problem with using this way? – Alireza Amini May 29 '22 at 16:52
  • It's best to provide some sort of explanation in an answer to how the code fixes a problem presented in the question. Otherwise, the community generally sees code-only answers as "low quality" which can contribute to downvotes. In some cases, the answer could be deleted. The goal of SO is to not only help the asker, but future visitors. – codewario May 29 '22 at 16:59
  • This isn't an admonishment, but rather a tip for writing quality answers. – codewario May 29 '22 at 16:59
  • thank u for your complete answer. i will send better answers since now. – Alireza Amini May 29 '22 at 18:19
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31880214) – MD. RAKIB HASAN May 31 '22 at 10:31