views:

463

answers:

3

Hello, If i have the following code example:

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

    public string Name { get; set; }
}

public class ClassA : ClassBass
{
    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 ClassBass ?

Thanks in advance.

+1  A: 

You can't, that's the whole point of inheritance: the subclass must offer all methods and properties of the base class.

You could change the implementation to throw an exception when the property is called (if it were virtual)...

Fried Hoeben
+7  A: 

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.

P.S. In the programming world, Base is spelled with an 'e' meaning that it's at the bottom of the pile - the foundation. Bass refers to either beer, music or fish - just saying.

BenAlabaster
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.
Brian Hasden
Thanks Brian, I should've thought to mention that, good catch.
BenAlabaster
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 - I had already mentioned that
BenAlabaster
Yeah, you must've add that just as I was posting my comment. Oh well, just trying to help.
Brian Hasden
No worries ;) [15 chars]
BenAlabaster
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
Grizzly
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.
Brian Hasden
@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.
BenAlabaster
+2  A: 

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, it appears like this (per Reflector):

[Browsable(false), Bindable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
    EditorBrowsable(EditorBrowsableState.Never)]
public override string Text
{
    get { return base.Text; }
    set { base.Text = value; }
}

Browsable indicates whether the member shows up in the Property window. EditorBrowsable indicates whether it shows up in the Intellisense dropdown. You can still type the property if EditorBrowsable is set to false, and it'll still build, but it won't be as obvious that you can use it.

Kyralessa