curiousBoy
curiousBoy

Reputation: 6834

How to limit protected member to be accessible from only first level child C#

I have 3 level classes.

And MiddleClass is derived from TopClass and BottomClass is derived from MiddleClass.

I want to have a property in TopClass which could only be accessible from TopClass and MiddleClass not the BottomClass.

As I am using protected access modifier, the protected property in TopClass is accessible from BottomClass.

Here are my classes to give better insight.

public class TopClass
 {
    private string ThisIsOnlyAccessibleForTopClass { get; set; } 
    protected string ThisIsOnlyAccessibleForTopClassAndMiddleClass { get; set; } // I want this to be accessible only by the MiddleClass 
    public string AccessibleFromEverywhere { get; set; } // this is good as it is public so accessible everywhere

    public virtual void SomeWeirdFunction()
    {
       ThisIsOnlyAccessibleForTopClass = "I can access this here as it is grand father's private member!"; 
    }
 }


 public class MiddleClass : TopClass
 {
     public override void SomeWeirdFunction()
     {
         base.ThisIsOnlyAccessibleForTopClassAndMiddleClass = "As this is a MiddleClass class, I am accessible here.. That is good!";
     }
 }


 public class BottomClass : MiddleClass
 {
     public override void SomeWeirdFunction()
     {
         base.ThisIsOnlyAccessibleForTopClassAndMiddleClass = "I don't want this to be accessible here!";
     }
 }

I want ThisIsOnlyAccessibleForTopClassAndMiddleClass to be only accessible from the MiddleClass and TopClass, not from BottomClass.

How can I do that? And as I cannot do this with existing access modifiers such as protected, public, internal , private etc.. is it a sign that I am trying to break some sort of rule here?

Upvotes: 8

Views: 998

Answers (1)

Joe Sewell
Joe Sewell

Reputation: 6610

If you have a specific MiddleClass that should have privileged access to a member of TopClass, you can put MiddleClass in TopClass as a nested type. Nested types have access to all members of their enclosing type.

public class TopClass
{
    private string ThisIsOnlyAccessibleForTopClass { get; set; } 
    private string ThisIsOnlyAccessibleForTopClassAndMiddleClass { get; set; } // I want this to be accessible only by the MiddleClass 
    public string AccessibleFromEverywhere { get; set; } // this is good as it is public so accessible everywhere

    public virtual void SomeWeirdFunction()
    {
        ThisIsOnlyAccessibleForTopClass = "I can access this here as it is grand father's private member!"; 
    }

    public class MiddleClass : TopClass
    {
        public override void SomeWeirdFunction()
        {
            base.ThisIsOnlyAccessibleForTopClassAndMiddleClass = "As this is a MiddleClass class, I am accessible here.. That is good!";
        }
    }

}

public class BottomClass : TopClass.MiddleClass
{
    public override void SomeWeirdFunction()
    {
        // compilation error:
        // base.ThisIsOnlyAccessibleForTopClassAndMiddleClass = "I don't want this to be accessible here!";
    }
}

If you have one or more MiddleClass classes in the same assembly as TopClass, and all the BottomClass classes are going to be in another assembly, you can use private protected. It means "access to only classes that are BOTH internal and protected", whereas protected internal means "access to classes that are EITHER internal or protected".

// in Assembly A

public class TopClass
{
    private string ThisIsOnlyAccessibleForTopClass { get; set; } 
    private protected string ThisIsOnlyAccessibleForTopClassAndMiddleClass { get; set; } // I want this to be accessible only by the MiddleClass 
    public string AccessibleFromEverywhere { get; set; } // this is good as it is public so accessible everywhere

    public virtual void SomeWeirdFunction()
    {
        ThisIsOnlyAccessibleForTopClass = "I can access this here as it is grand father's private member!"; 
    }
}

public class MiddleClass : TopClass
{
    public override void SomeWeirdFunction()
    {
        base.ThisIsOnlyAccessibleForTopClassAndMiddleClass = "As this is a MiddleClass class, I am accessible here.. That is good!";
    }
}

// in Assembly B, which references Assembly A

public class BottomClass : MiddleClass
{
    public override void SomeWeirdFunction()
    {
        // compile error
        // base.ThisIsOnlyAccessibleForTopClassAndMiddleClass = "I don't want this to be accessible here!";
    }
}

Upvotes: 8

Related Questions