4

First of all let me start by saying that I do understand access specifiers I just don't see the point of using them in classes. It makes sense on methods to limit their scope but on classes, why would you want a private class, isn't it the purpose of classes to be able to reuse them?

What is the purpose of access specifiers when declaring a class in C#? When would you use them?

Thanks

fs_tigre
  • 10,650
  • 13
  • 73
  • 146
  • You should read about namespaces. – Hamid Pourjam Mar 03 '16 at 13:58
  • 2
    When you want to limit the surface area of your public API is one reason. Think about encapsulation and what that means... Do you really want your consumers to see internal implementation details if they never need to touch them? What about private nested classes that are used within the context of a single class... Etc – Charleh Mar 03 '16 at 14:00
  • 1
    You could have a large class and inside a `private class`. Then you can create an instance of it in the surrounding class but not from outside. Maybe this inner class is so specific that it should not be reused elsewhere. – Tim Schmelter Mar 03 '16 at 14:01
  • 1
    Well, no, the purpose of a class in C# is to be able to write code. Encapsulation is a cornerstone of software design. The less you expect a class to do and the less it is exposed to other code, the less likely the code in that class will break. – Hans Passant Mar 03 '16 at 14:09
  • Thank you all for the good information. – fs_tigre Mar 03 '16 at 14:51

5 Answers5

6

Well, let's say that you want a class to be only accessed inside her own assembly:

internal class Test

Let's say that you have two classes, one inside the other (nested classes):

protected internal class TestA
{
    private TestB _testB;

    private class TestB
    {
    }

    public TestA()
    {
        _testB = new TestB();
    }
}

The TestB class can be only accessed inside methods/properties/contructors inside TestA or inside herself.

The same applies to the protected modifier.

// Note

If you don't specify the access modifier, by default it will be private, so on my example the following line:

private TestB _testB;

is equal to

TestB _testB;

And the same applies to the class.

Special Modifier

Then, there is the protected internal which joins both modifiers so you can only access that class inside the same assembly OR from a class which is derived by this one even if it isn't in the same assembly. Example:

Assembly 1:

public class TestA : TestB
{
    public TestB GetBase()
    {
        return (TestB)this;
    }

    public int GetA1()
    {
        return this.a1;
    }
}
protected internal class TestB
{
    public int a1 = 0;
}

Program

TestA _testA = new TestA(); // OK
TestB _testB = new TestB(); // ERROR

int debugA = new TestA().a1 // ERROR
int debugB = new TestA().GetA1(); // OK

TestB testB_ = new TestA().GetBase(); // ERROR

Source

Link (Access Modifiers)

The type or member can be accessed by any code in the same assembly, but not from another assembly.

The type or member can be accessed only by code in the same class or struct.

The type or member can be accessed only by code in the same class or struct, or in a class that is derived from that class.

The type or member can be accessed by any other code in the same assembly or another assembly that references it.

Leandro Soares
  • 2,902
  • 2
  • 27
  • 39
  • If I understand this correctly, this is more for people creating public APIs, if my assumption is correct, I could leave all of my classes without access specifiers for personal/local projects since the default is `internal`, correct? – fs_tigre Mar 03 '16 at 14:55
  • The default is `private`, normally people just use `public` because it's simple and doesn't require code evaluation. But it's all about patterns, maintenance, flexibility and security. – Leandro Soares Mar 03 '16 at 15:02
  • 1
    Thanks a lot for the clarification. – fs_tigre Mar 03 '16 at 15:09
3

I will give you an example of an internal class. Imagine I have some DLL. Form this DLL I want to expose only a single class called A. This class A however, should have access to other classes inside DLL - thus I will make all other classes inside DLL internal. Hence, from the DLL you can only use class A, while A can still access other classes inside DLL - you however, can't.

Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
3

The greatest benefit of using access specifiers is when someone else is using your classes. By clearly specifying, what should and what should not be touched within your objects, you can protect your object internal mechanism and integrity from being misused or damaged.

With bigger classes, if you made everything public, you would also make it harder for the user of your code to work with IntelliSense, which is something that is very handy when you deal with unknown libraries.

Wapac
  • 4,058
  • 2
  • 20
  • 33
0

I have created one application to understand Access Specifiers.

It will be more easy to understand it with code instead of Theory.

I have added my notes in code, for better guidance.

namespace ConsoleApplication1
{
    //A normal public class which contains all different types of access-modifier classes in the assembly named 'ConsoleApplication1'
    public class Base
    {
        public class PublicBase
        {
            public static void fn_PublicBase()
            {
                Console.WriteLine("fn_PublicBase");
            }
        }
        private class PrivateBase
        {
            public static void fn_PrivateBase()
            {
                Console.WriteLine("fn_PrivateBase");
            }
        }

        protected class ProtectedBase
        {
            public static void fn_ProtectedBase()
            {
                Console.WriteLine("fn_ProtectedBase");
            }
        }

        internal class InternalBase
        {
            public static void fn_InternalBase()
            {
                Console.WriteLine("fn_InternalBase");
            }
        }

        protected internal class ProInternalBase
        {
            public static void fn_ProInternalBase()
            {
                Console.WriteLine("fn_ProInternalBase");
            }
        }       

        //TIP 1:This class is inside the same class 'Base' so everything is accessible from above.Hurray!!
        class Base_Inside
        {
            public static void fn_Base_Inside()
            {
                //All methods are easily accessible.Does not consider a modified indeed.
                PublicBase.fn_PublicBase();
                PrivateBase.fn_PrivateBase();
                ProtectedBase.fn_ProtectedBase();
                InternalBase.fn_InternalBase();
                ProInternalBase.fn_ProInternalBase();
            }
        }
    }

    //Different class but inside the same assembly named 'ConsoleApplication1'
    public class Base_Sibling  : Base
    {        
        //TIP 2:This class is NOT in same class 'Base' but in the same assembly so  only protected is NOT accessible rest all are accessible.        
        public void fn_Base_Sibling()
        {
            PublicBase.fn_PublicBase();
            //PrivateBase.fn_PrivateBase();     //ERROR:Accesibility of 'protected'            
            ProtectedBase.fn_ProtectedBase();   //protected is accessible because Base_Sibling inherit class 'Base'. you can not access it via Base.ProtectedBase
            InternalBase.fn_InternalBase();
            ProInternalBase.fn_ProInternalBase();
        }
    }
}

Now to Understand difference between internal, protected internal, I Have added one for project named with Assembly_1 in same solution.

I have inherited Base class of ConsoleApplication1 to Derived class of Assembly_1.

namespace Assembly_1
{
    //TIP:if it does not inherit class 'ConsoleApplication1.Base' then we can not access any thing beacuse this is different assembly.
    //TIP:only INTERNAL is NOT accessible , rest all are accessible from first assembly if it inherits class 'Soul'
    public class Derived : ConsoleApplication1.Base
    {
        public class PublicDerived
        {
            public static void fn_PublicDerived()
            {
                PublicBase.fn_PublicBase();             //YES, becuase this is 'public'
              //PrivateBase.fn_PrivateBase();           //No, becuase this is 'private'
                ProtectedBase.fn_ProtectedBase();       //YES, becuase this is 'protected'
              //InternalBase.fn_InternalBase();         //No, becuase this is 'internal'
                ProInternalBase.fn_ProInternalBase();   //YES, becuase this is 'protected internal'
            }
        }
    }
}
Bharat
  • 5,869
  • 4
  • 38
  • 58
0

- Update answer 2019 -

Hi You can find accessibility via below table

enter image description here

Andi AR
  • 2,678
  • 2
  • 23
  • 28