52

I want to hide the base public property(a data member) in my derived class:

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}

class a
{
    public int item1 {get; set;}
    public int item2 { get; set; }
}

class b : a
{
    new private int item1;
}

class c : a
{

}

i have member as public because i want the member to be inherited in c class , but want to hide the member in b class , how can i do this ?

dont i have an option to selectively inherite the variable i want in my base class ??? thats really bad , i think ms should provide us with an option (may be a modifier) to perform this


Edit:

I found the answer myself (i heard lots of them telling this is not possible in c#, but you can kind of do it)

I am including the code in case it is useful

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4; // shows an error  : )
    }
}

class a
{
    public int item1 { get; set; }
    public int item2 { get; set; }
}

class b : a
{
    new public static int item1
    {
        get;
        private set;
    }
}
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
ravikiran
  • 1,327
  • 5
  • 14
  • 18
  • Is this code compiling correctly? – vpram86 Sep 18 '09 at 11:15
  • I am sure if you tell us the use case, there is an alternate solution. Why you want to do this? – P.K Sep 18 '09 at 11:21
  • Your solution obviously only hides the setter. While it stops the immediate assignment, there is nothing to stop the following: ((a)obj).item1 = 4; b cannot be programmed under the assumption that item1 will never change, as it might. It stops the simple case but not every case. A more robust solution would be to re-architecture the inheritance hierarchy. – ICR Sep 18 '09 at 13:18
  • 4
    Composition. Maybe even worth an anwer. – Dykam Sep 19 '09 at 12:38
  • 3
    This is such a bad idea! It breaks the whole concept of OO inheritance and polymorphism. Why would you _ever_ want to do this? – Basic Dec 03 '14 at 08:14
  • 2
    For me, im doing this because I am creating an api. My api objects inherit from the base class object, but protect some of the properties and methods that most coders shouldn't change. – DidIReallyWriteThat Jul 10 '15 at 14:53
  • Inheritance must repect the [Liskov substitution principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle). The language and your API's clients will rely on it. By removing a base class' property, you are clearly violating it. – Alexandre C. Oct 18 '15 at 09:39
  • 1
    Why not just create a class with the class you want to extend in it. Then just expose whichever properties you want through accessors? I think Dykam was alluding to this. I do this when I want to simplify a class - show only the properties I care about and have code in the accessors to transform the behavior of base class properties. – AndrewBenjamin Jul 01 '16 at 00:52

17 Answers17

29

I'm going to attempt to explain with examples why this is a bad idea, rather than using cryptic terms.

Your proposal would be to have code that looks like this:

public class Base
{
    public int Item1 { get; set; }
    public int Item2 { get; set; }
}


public class WithHidden : Base
{
    hide Item1; // Assuming some new feature "hide" in C#
}

public class WithoutHidden : Base { }

This would then make the following code invalid:

WithHidden a = new WithHidden();
a.Item1 = 10; // Invalid - cannot access property Item1
int i = a.Item1; // Invalid - cannot access property Item1

And that would be just what you wanted. However, suppose we now have the following code:

Base withHidden = new WithHidden();
Base withoutHidden = new WithoutHidden();

SetItem1(withHidden);
SetItem1(withoutHidden);

public void SetItem1(Base base)
{
    base.Item1 = 10;
}

The compiler doesn't know what runtime type the argument base in SetItem1 will be, only that it is at least of type Base (or some type derived from Base, but it can't tell which -- it may be obvious looking at the code snippet, but more complex scenarios make it practically impossible).

So the compiler will not, in a large percentage of the cases, be able to give a compiler error that Item1 is in fact inaccessible. So that leaves the possibility of a runtime check. When you try and set Item1 on an object which is in fact of type WithHidden it would throw an exception.

Now accessing any member, any property on any non-sealed class (which is most of them) may throw an exception because it was actually a derived class which hid the member. Any library which exposes any non-sealed types would have to write defensive code when accessing any member just because someone may have hidden it.

A potential solution to this is to write the feature such that only members which declare themselves hideable can be hidden. The compiler would then disallow any access to the hidden member on variables of that type (compile time), and also include runtime checks so that a FieldAccessException is thrown if it is cast to the base type and tried to be accessed from that (runtime).

But even if the C# developers did go to the huge trouble and expense of this feature (remember, features are expensive, especially in language design) defensive code still has to be written to avoid the problems of potential FieldAccessExceptions being thrown, so what advantage over reorganising your inheritance hierarchy have you gained? With the new member hiding feature there would be a huge number of potential places for bugs to creep into your application and libraries, increasing development and testing time.

ICR
  • 13,896
  • 4
  • 50
  • 78
  • 1
    While `public` members of a base class should generally be visible in derived classes, many classes inherit `protected` members which should not be visible in derived classes. I would posit, for example, that 99% of classes expose `MemberwiseClone` to sub-derived classes, but that in the majority of cases (including `List` and `Dictionary`, both of which could benefit from `Clone` methods) it is not possible for sub-derived classes to make `MemberwiseClone` work usefully, and the member should thus be hidden. Replacement with an `Obsolete` method is perhaps best, but... – supercat Apr 03 '15 at 21:30
  • 1
    I know this answer is old, but in your example the `SetItem1()` method should be able to access the `Item1` property because it is working with the `Base` type. Hiding a base member doesn't remove it completely. It just makes it invisible when working with that type or a type that derives from it. I think this would be useful. It allows you to simplify the interface of derived classes when you know that base members don't make sense in that context. – Jonathan Wood Oct 04 '20 at 17:58
  • This answer is unclear, as hiding members using the `new` keyword was always possible. In this regard, the comments which say `Assuming some new feature "hide" in C#` and `Invalid - cannot access property Item1` are wrong. – OfirD Sep 14 '22 at 11:22
17

What you want to do goes directly against the grain of OO, you can't 'unpublish' members as this violates the substitution principle. You have to refactor this into something else.

H H
  • 263,252
  • 30
  • 330
  • 514
  • So Eiffel gets this wrong, as it allows you to `undefine` members of the base class? – Joey Sep 18 '09 at 11:21
  • I don't know Eiffel but how do they handle `a a1 = new b()` ? – H H Sep 18 '09 at 11:23
  • Ah, my mistake, I think. You can undefine things but apparently you need to have one feature of the same name in the class anyway. But with multiple inheritance it's not very clear where it comes from (especially when there are name clashes). – Joey Sep 18 '09 at 11:25
  • common thats gross , all i want to do is to selectivelly inherit the variable i require in my base class , how is this against the principle of oo ? – ravikiran Sep 18 '09 at 11:31
  • In OO, a derived class is a subset with added functionality. You should check the condition: _b_ IS-A _a_. And please use PascalCasing for class names. – H H Sep 18 '09 at 12:29
  • That is wrong. It has nothing to do with OO, but with the implementation how **C#** does it. In C++ for example it is perfectly possible without 'unpublishing' anything, it's called [protected inheritance](https://stackoverflow.com/a/1372858/1810087) and comes in quite handy sometimes. Were does anything OO related states you can't change visibility of inheritance? – user1810087 Dec 14 '18 at 10:05
  • Protected inheritance changes nothing, the same Liskov Substitution argument still holds for derived classes. And that is very much the core of OO. – H H Dec 14 '18 at 15:20
7

Vadim's response reminded me of how MS achieve this in the Framework in certain places. The general strategy is to hide the member from Intellisense using the EditorBrowsable attribute. (N.B. This only hides it if it is in another assembly) Whilst it does not stop anyone from using the attribute, and they can see it if they cast to the base type (see my previous explination) it makes it far less discoverable as it doesn't appear in Intellisense and keeps the interface of the class clean.

It should be used sparingly though, only when other options like restructuring the inheritance hierarchy would make it a lot more complex. It's a last resort rather than the first solution to think of.

ICR
  • 13,896
  • 4
  • 50
  • 78
5

The only thing I can think of is to make item1 virtual in class a:

class a
{
    public virtual int item1 { get; set; }
    public int item2 { get; set; }

}

and then override it in class b but throw an exception in getter and setter. Also if this property is used in a visual designer you can use Browsable attribute to not display.

class b : a
{
    [Browsable(false)]
    public override int item1
    {
        get
        {
            throw new NotSupportedException();
        }
        set
        {
            throw new NotSupportedException();
        }
    }
}
Neil Thompson
  • 6,356
  • 2
  • 30
  • 53
Vadim
  • 21,044
  • 18
  • 65
  • 101
5

If you use an interface instead of a base class for defining the property, you could implement the property explicitly. The would require an explicit cast to the interface to use the property.

public interface IMyInterface
{
    string Name { get; set; }
}

public class MyClass : IMyInterface
{

    string IMyInterface.Name { get; set; }

}

You can find more out here.

Christopher Stevenson
  • 2,843
  • 20
  • 25
  • I found this to be a nice way to contain everything to a single class definition, and make it obvious through naming that consumers probably shouldn't cast to the interface, e.g. something like `IMyFactoryInterface` – MechEthan Jan 20 '18 at 19:55
2

First of all this is not good idea if you using some methods, that operates base class.
You can try to use obsolete argument to make users twice think to use this property.

[System.Obsolete("Do not use this property",true)]  
public override YourType YourProperty { get; set; }
StNickolas
  • 576
  • 7
  • 20
0

You can override it and then Add a [Browsable(false)] tag to prevent showing it in designer.

Simple:

public class a:TextBox
{
        [Browsable(false)]
        public override string Text
        {
            get { return ""; }
            set { }
        }
}
pingsft
  • 316
  • 3
  • 4
0

What you are describing is something akin to 'private inheritance' from C++, and is not available in C#.

Jason
  • 28,040
  • 10
  • 64
  • 64
0

You cant do it directly, but you could override the properties in the child class and make them readonly e.g.

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}

class a
{
    public virtual int item1 {get; set;}
    public virtual int item2 { get; set; }

}

class b : a
{
    public override int item1
    { 
         get { return base.item1; }
         set { }
    }
}

    class c : a
{

}
JDunkerley
  • 12,355
  • 5
  • 41
  • 45
0

You could use interfaces to hide the property. The child class would implemented an interface that didn't have the property then it wouldn't appear.

You would need two interfaces for when you want the property and when you don't, thus making it a horrible hack.

BeerHugger
  • 103
  • 1
  • 7
0

Changing the accessibility of a virtual member is an inheriting class is specifically prohibited by the C# language spec:

The override declaration and the overridden base method have the same declared accessibility. In other words, an override declaration cannot change the accessibility of the virtual method. However, if the overridden base method is protected internal and it is declared in a different assembly than the assembly containing the override method then the override method’s declared accessibility must be protected.

From section 10.6.4 Override methods

The same rules which apply to overriding method also apply to properties, so going from public to private by inheriting from the base class can't be done in C#.

Paul Turner
  • 38,949
  • 15
  • 102
  • 166
  • Since there was no clarification to this effect, I thought I should add the strong reason why this change can't be done. – Paul Turner May 24 '13 at 15:22
0

What you actually need are interfaces:

    public interface ProvidesItem1
    {
        int item1 { get; set; }
    }

    public interface ProvidesItem2
    {
        int item2 { get; set; }
    }

    class a : ProvidesItem1, ProvidesItem2
    {
        public int item1 { get; set; }
        public int item2 { get; set; }
    }

    class b : ProvidesItem1
    {
        public int item1 { get; set; }
    }

Then just pass the interfaces around. If the classes should use a common implementation, put that in a third class and let them derive from that class aswell as implement their respective interface.

David
  • 818
  • 13
  • 30
0

Yes, it is possible. What say you on the delegation. I will try to give an idea of what is called "delegation" in OOP with a piece of code:

public class ClassA
{
    // public
    public virtual int MyProperty { get; set; }

    // protected
    protected virtual int MyProperty2 { get; set; }
}

public class ClassB
{
    protected ClassC MyClassC;

    public ClassB()
    {
        MyClassC = new ClassC();
    }

    protected int MyProperty2
    {
        get { return MyClassC.MyProperty2; }
        set { MyClassC.MyProperty2 = value; }
    }

    protected int MyProperty
    {
        get { return MyClassC.MyProperty; }
        set { MyClassC.MyProperty = value; }
    }

    protected class ClassC : ClassA
    {
        public new int MyProperty2
        {
            get { return base.MyProperty2; }
            set { base.MyProperty2 = value; }
        }

        public override int MyProperty
        {
            get { return base.MyProperty; }
            set { base.MyProperty = value; }
        }
    }
}
Odrai
  • 2,163
  • 2
  • 31
  • 62
0
namespace PropertyTest    
{    
    class a
    {    
        int nVal;

        public virtual int PropVal
        {
            get
            {
                return nVal;
            }
            set
            {
                nVal = value;
            }
        }
    }

    class b : a
    {
        public new int PropVal
        {
            get
            {
                return base.PropVal;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            a objA = new a();
            objA.PropVal = 1;

            Console.WriteLine(objA.PropVal);

            b objB = new b();
            objB.PropVal = 10; // ERROR! Can't set PropVal using B class obj. 
            Console.Read();
        }
    }
}
Odrai
  • 2,163
  • 2
  • 31
  • 62
Abhishek Panchal
  • 394
  • 1
  • 11
0

You can user new modifer.

Sample;

public class Duck
{
    public string Color{get; set;}
    public void Swim() { }
}
public class DonaldDuck : Duck
{
    new public void Swim() 
    { 
        /*you could call in DonaldDuck.Swim  only here but not public for DonaldDuck client.*/ 
    }
}
Nuri YILMAZ
  • 4,291
  • 5
  • 37
  • 43
0

It was mentioned in the thread before, but I think the answer you are looking for is composition.

So instead of "ObjectB is an ObjectA" (inheritance), you would have an "ObjectB has an ObjectA" (composition) relationship.

In code:

public class A
{
    public int PropA { get; set; }
    public int PropB { get; set; }
}

public class B
{
    private readonly A a;

    public B()
    {
        a = new A();
    }

    // Only expose from A what you need
    public int PropB
    {
        get
        {
            return a.PropB;
        }

        set
        {
            a.PropB = value;
        }
    }
}
JoelB
  • 1
-1

If you wanna hide a member from base class then you will need to add a new base class let's call it baseA and your code should be as follows:

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}

class baseA
{
    public int item2 { get; set; }
}
class a:baseA
{
    public int item1 { get; set; }        
}

class b : baseA { }

class c : a { }
Muhammad Assar
  • 659
  • 7
  • 16
Memo
  • 329
  • 3
  • 5