How to choose between private and protected access modifier to encapsulate members between base and childs classes?

I am trying on a project to use private values in my internal functions. In past I used only public ones, but I noticed that obfuscation is working much better when using as much as possible private parameters.

My question is regarding Parent/Child classes.

In my main class I define all the parameters as following :

public class MyFatherClass
{
    private long id = -1;
    public long ID { get { return this.id; } set { this.id = value; } }    
    ...
}

So in all internal functions I access to my private value instead of the public one.

Then in my daughter class I just add parameters specific to the child class.

public class MyChildClass : MyFatherClass
{
    private long anotherParameter = -1;
    public long AnotherParameter { get { return this.anotherParameter; } set { this.anotherParameter = value; } }    
    ...
}

Just, I see that in my Parent class, I can access to id and ID without problem, but from daughter classes I can only access ID(as id is private).

If I understood correct, I would need to replace all private by protected in my parent lass, so it would solve the problem? What I don't understand is the code is working even if I leave it so. Why don't I have an error message, when I set ID value in daughter class, the sentence this.id=value is executed, but how can can I access to it from my child class if it is private?

I am now hesitating, may I just add a private id in each child class, or may I set id to protected in my parent class?

Thanks for your explanations.

Edit, just adding a screenshot of my reversed code after obfuscation, so you could understand difference on how are obfuscated private/public methods/fields

enter image description here


Why don't I have an error message, when I set ID value in daughter class, the sentence this.id=value is executed, but how can can I access to it from my child class if it is private?

When you call a public method on a class, that method can access private members of that class:

public class Foo
{
    public void Bar()
    {
        Baz();
    }

    private void Baz()
    {
        // private method called by public method
    }
}   

var foo = new Foo();
foo.Bar();

This compiles just fine. Your setter is the same: it's public, so callable from everywhere, even if it accesses private members.

As for making your field (private long id = -1;) protected: yes, that will mean you can access it in derived classes. But whether you want to is another question.

You have declared a public property for a reason. Perhaps you want to do some validation in its setter or getter. If not, if you're just using a property to access a private field, you could just ditch the entire private field and use an auto-implemented property:

public long ID { get; set; } = -1;

Then you can access the property everywhere, from within itself, from derived classes and from code using this class.

See also:

  • What is the difference between a field and a property?
  • What are Automatic Properties in C# and what is their purpose?

Here is a short and reduced description of what access modifiers do:

  • Public : fields (variables) and properties (variables encapsulation) and methods (functions and procedures) are visible and accessible by the class itslef, by its childs and by any other external classes.

  • Private : members (fields, properties and methods) are visible and accessible only by the class, not by its childs nor by any external class.

  • Protected : members are visible and accessible by the class and by its childs, but not by others classes.

  • Internal : members are visible and accessible by the class and by its childs and by any class that is in the same assembly (.exe and .dll), but not by a class from another assembly.

So you should set id to protected in the parent class to use it in the childs.

But here is the rule:

  • If childs classes can modify id you should set as a protected field, and offer a public property (get) if available for external items.

  • If childs classes are not allowed to modify it you should set it private and offer :

    • A propected property with only a getter if external items can't access it.

    • A public property with only a getter if external items can access it.

Don't repeat a member with the same name else it will hide the parent and can cause polymorphism problems, else you know what you do.

You can read these tutorials to more understand access modifier keywords:

C# Access Modifiers

Access Modifiers (C# Reference)

Here are some readings:

C# Tutorial Level 0
C# Tutorial Level 1
C# Tutorial Level 2
C# Tutorial Level 3

C# Snippets @ Techi.io

Beginning Visual C# 2008 Programming