How to hide an inherited property in a class without modifying the inherited class (base class)?

101,240

Solution 1

I smell a code smell here. It is my opinion that you should only inherit a base class if you're implementing all of the functionality of that base class. What you're doing doesn't really represent object oriented principles properly. Thus, if you want to inherit from your base, you should be implementing Name, otherwise you've got your inheritance the wrong way around. Your class A should be your base class and your current base class should inherit from A if that's what you want, not the other way around.

However, not to stray too far from the direct question. If you did want to flout "the rules" and want to continue on the path you've chosen - here's how you can go about it:

The convention is to implement the property but throw a NotImplementedException when that property is called - although, I don't like that either. But that's my personal opinion and it doesn't change the fact that this convention still stands.

If you're attempting to obsolete the property (and it's declared in the base class as virtual), then you could either use the Obsolete attribute on it:

[Obsolete("This property has been deprecated and should no longer be used.", true)]
public override string Name 
{ 
    get 
    { 
        return base.Name; 
    }
    set
    {
        base.Name = value;
    }
}

(Edit: As Brian pointed out in the comments, the second parameter of the attribute will cause a compiler error if someone references the Name property, thus they won't be able to use it even though you've implemented it in derived class.)

Or as I mentioned use NotImplementedException:

public override string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

However, if the property isn't declared as virtual, then you can use the new keyword to replace it:

public new string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

You can still use the Obsolete attribute in the same manner as if the method was overridden, or you can throw the NotImplementedException, whichever you choose. I would probably use:

[Obsolete("Don't use this", true)]
public override string Name { get; set; }

or:

[Obsolete("Don't use this", true)]
public new string Name { get; set; }

Depending on whether or not it was declared as virtual in the base class.

Solution 2

While technically the property won't be hidden, one way to strongly discourage its use is to put attributes on it like these:

[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]

This is what System.Windows.Forms does for controls that have properties that don't fit. The Text property, for instance, is on Control, but it doesn't make sense on every class that inherits from Control. So in MonthCalendar, for instance, the Text property appears like this (per the online reference source):

[Browsable(false),
    EditorBrowsable(EditorBrowsableState.Never),
    Bindable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}
  • Browsable - whether the member shows up in the Properties window
  • EditorBrowsable - whether the member shows up in the Intellisense dropdown

EditorBrowsable(false) won't prevent you from typing the property, and if you use the property, your project will still compile. But since the property doesn't appear in Intellisense, it won't be as obvious that you can use it.

Solution 3

Just hide it

 public class ClassBase
{
    public int ID { get; set; }
    public string Name { get; set; }
}
public class ClassA : ClassBase
{
    public int JustNumber { get; set; }
    private new string Name { get { return base.Name; } set { base.Name = value; } }
    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = 0;
    }
}

Note: Name will still be a public member of ClassBase, given the constraint of not changing the base class there is no way to stop that.

Solution 4

Why force inheritance when it's not necessary? I think the proper way of doing it is by doing has-a instead of a is-a.

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA
{
    private ClassBase _base;

    public int ID { get { return this._base.ID; } }

    public string JustNumber { get; set; }

    public ClassA()
    {
        this._base = new ClassBase();
        this._base.ID = 0;
        this._base.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}

Solution 5

I don’t think a lot of the people replying here understand inheritance at all. There is a need to inherit from a base class and hide its once public var’s and functions. Example, lets say you have a basic engine and you want to make a new engine that is supercharged. Well, 99% of the engine you will use but you will tweak a bit of its functionality to make it run much better and yet still there is some functionality that should only be shown to the modifications made, not the end user. Because we all know that every class MS puts out doesn’t really ever need any modifications.

Besides using the new to simply override the functionality it is one of the things that Microsoft in their infinite wis….. oh, I mean mistakes considered a tool not worthwhile anymore.

The best way to accomplish this now is multi-level inheritance.

public class classA 
{
}

public class B : A 
{} 

public class C : B 
{} 

Class B does all your work and class C exposes what you need exposed.

Share:
101,240
Ahmed Magdy
Author by

Ahmed Magdy

My name is Ahmed Magdy, I'm working as Senior Customer Engineer <developer /> at Microsoft with 16+ years experience in software development. LinkedIn - Stackoverflow Careers - @amgdy Founder of HackItRight - @hackitright

Updated on July 08, 2022

Comments

  • Ahmed Magdy
    Ahmed Magdy almost 2 years

    If i have the following code example:

    public class ClassBase
    {
        public int ID { get; set; }
    
        public string Name { get; set; }
    }
    
    public class ClassA : ClassBase
    {
        public int JustNumber { get; set; }
    
        public ClassA()
        {
            this.ID = 0;
            this.Name = string.Empty;
            this.JustNumber = string.Empty;
        }
    }
    

    What should I do to hide the property Name (Don't shown as a member of ClassA members) without modifying ClassBase ?

  • Brian Hasden
    Brian Hasden over 14 years
    The obsolete attribute also has a second parameter that specifies that using the property should be considered an error. At that point you should get a compile time error, which is helpful.
  • BenAlabaster
    BenAlabaster over 14 years
    Thanks Brian, I should've thought to mention that, good catch.
  • Brian Hasden
    Brian Hasden over 14 years
    I believe you can also use the "new" keyword to specify new functionality for the property even if it's not marked virtual. That would allow him to mark the property as obsolete even if it's from a class where the property wasn't virtual.
  • Brian Hasden
    Brian Hasden over 14 years
    Yeah, you must've add that just as I was posting my comment. Oh well, just trying to help.
  • Grizzly
    Grizzly over 14 years
    One should also mention that while the use of new will hide the original implementation of the property for the derived class, the original implementation will still be used when the object is cast to the base class, which can lead to nasty bugs
  • Brian Hasden
    Brian Hasden over 14 years
    Very true. Obviously what the user who posted the question is trying to do is incorrect. I don't think there's any foolproof way to accomplish what he's trying to do.
  • BenAlabaster
    BenAlabaster over 14 years
    @Grizzly - We did point out that it was a bad idea before we told the OP how to achieve it. That's one of the side effects.
  • supercat
    supercat almost 13 years
    Public methods of a base class should be implemented in derived classes per the LSP; protected properties have no such requirement (since the only way to access protected members is from the base object instance, which is always of the base type). What's the preferred way to hide protected members from sub-derived classes (e.g. to prevent a derived class from calling "MemberwiseClone")?
  • Alex Essilfie
    Alex Essilfie over 9 years
    With this method, doing something like ClassA.Name outside ClassA will expose the ClassBase.Name property. It is not possible to new a member to a more restricted access than it was originally declared.
  • Alex Essilfie
    Alex Essilfie over 9 years
    What I would give for Microsoft to provide the ability (via a new keyword, attribute or other means) to effectively hide unwanted members in derived classes. Then I could just use the UserControl class instead of doing so much work when I inherit the Control class.
  • CCondron
    CCondron over 9 years
    That is the point of the note. Name will not be a public member of ClassA as per the question. For serialization and reflection this can be important.
  • Alex Essilfie
    Alex Essilfie over 9 years
    Yes, that's true. It is however worthy of note that when one wants to hide a member from an inherited class, it can be because he is setting the member's value to one of a set of predefined values and so changing it can result in unexpected behaviour.
  • CCondron
    CCondron over 9 years
    Agreed, and given the constraint of not changing the base class there is no way to stop that.
  • Alex Essilfie
    Alex Essilfie over 9 years
    Agreed. After all, when pushed, one can use reflection to modify even private members.
  • Kira
    Kira about 7 years
    I think this code is specific to winforms or ASP maybe Xamarin forms. Mention it in your answer
  • SkyFighter
    SkyFighter over 6 years
    Instead of all the rhetoric about why this shouldn't be done... THIS is the actual answer I was looking for. For serialization purposes I really needed this. This provide the solution I needed perfectly! Thanks very much!
  • PeteH
    PeteH about 2 years
    you have a text box. Except you want to subclass it so that it only accepts numbers, say. The .Text property (a string) is meaningless here. It might have some value, if it were an int or a double, but as a string, it is useless. Because the correct place for input-to-number conversions is inside the subclass. Are you suggesting that the control should not inherit from TextBox? That's an example of why you might want to do it.