Home  >  Article  >  Backend Development  >  Access Modifiers in C#

Access Modifiers in C#

WBOY
WBOYOriginal
2024-09-03 15:24:47590browse

This article covers the most elementary concept of object-oriented programming from the C# programming language perspective. The concept is known as – Access Modifiers. The very first question to answer is – What are Access Modifiers? Simply put, access modifiers control which objects/variables/constants/methods (practically everything) can be accessed in which part of the code. Access modifiers play an important role in proofing the concept of Abstraction in Object-oriented programming. They control what part of the program should be and should not be visible to the end-user. Of course, an end-user is least concerned about the constants and variables involved in the algorithm. He is only concerned about what method he needs to invoke to get the output.

Types of Access Modifiers in C#

C# provides us with four types of access modifiers:

  • Private (the default access modifier, except enums and interfaces)
  • Protected (slightly restricted)
  • Public (unrestricted, the default choice for enums and interfaces)
  • Internal (public within the same assembly)

Apart from these four access modifiers, there are two more access level combinations–

  • Protected Internal
  • Private Protected

Let us understand each with an example.

1. Private

Private is the most restricted access level. It is also the default access modifier for all constants, variables, user-defined objects, etc. Only enums and interfaces are public by default. So, if you do not specify any access modifier, C# assigns the default modifier to it.

Private objects are not accessible outside the body of the class or struct, or program section in which they are declared. Any attempt to access the object outside the scope of the body in which it is declared results in a compile-time error.

Example #1

using System;
class Employee //private by default
{
string name; //private by default
public string GetName()
{
return name;
}
public void SetName(string name)
{
this.name = name;
}
}
public class Program
{
public static void Main()
{
Employee emp = new Employee();
emp.SetName("John");
Console.Write("Employee name is " + emp.GetName());
// compile time error - 'Employee.name' is inaccessible due to its protection level
// Console.Write("Employee name is " + emp.name);
}
}

Output:

Access Modifiers in C#

Example #2

using System;
public class Program
{
public static void Main()
{
int x = 5; //private to the Main method, accessible inside nested code blocks in the Main method
if (true)
{
int y = 10; //private to the if block, not accessible outside if block
Console.WriteLine("x = " + x);
Console.WriteLine("y = " + y);
}
Console.WriteLine("x = " + x);
// compile-time error - The name 'y' does not exist in the current context.
// Console.WriteLine("y = " + y);
}
}

Output:

Access Modifiers in C#

2. Protected

The Protected access specifier restricts an object to be accessible only from derived instances of the class. So, if a child class object tries to access a parent class’s protected objects, it is allowed. Non-derived classes cannot access protected members of any class. Of course, protected objects are accessible to methods of their own class.

Example:

using System;
class Parent
{
protected string x;
public Parent()
{
x = "abc"; //accessible to own class methods
}
}
class Child : Parent // derived class
{
public static void Main()
{
var parentObj = new Parent();
var childObj = new Child();
Console.WriteLine(childObj.x); //accessible to derived class object instances
// compile-time error - Cannot access protected member 'Parent.x' via a qualifier of type 'Parent'; the qualifier must be of type 'Child' (or derived from it)
// Console.WriteLine(parentObj.x);
}
}

Output:

Access Modifiers in C#

3. Public

This is the least restricted access modifier. Public objects are practically accessible to the whole outside world, thereby making them the highest permissible access modifier. Of course, this comes at a heavy cost – the cost of least protection.

Any part of the code can access public members. This makes them the least secure. Any code logic can modify their value which may lead to unexpected behavior. So, one must be very cautious before making any object public.

In the same Employee class that we created in our private access modifier example, if we change the public’s access level, we would not need any Getter and Setter methods. In fact, the best practice is to make the object private and use C# Getter and Setter properties.

Example:

using System;
class Employee
{
public string name;
}
public class Program
{
public static void Main()
{
Employee emp = new Employee();
emp.name = "John";
Console.Write("Employee name is " + emp.name);
}
}

Output:

Access Modifiers in C#

4. Internal

Internal objects and methods are only accessible within the same assembly. This is a very useful access modifier when you want to make any object public and yet do want to restrict its access only to the framework that you are coding.

So, in essence, all internal objects are accessible by all areas of the same assembly.

Let us create two console applications to understand this working.

Example:

Step 1: Create a C# Console Application and place the below code in it:

using System;
namespace ConsoleApp1
{
public class Parent
{
internal int x;
public Parent()
{
x = 10;
}
}
public class Program
{
public static void Main()
{
var parentObj = new Parent();
// accessible within the same assembly
Console.Write("The value of x = " + parentObj.x);
}
}
}

Step 2: Build the solution to get the .dll file from the bin folder.

Access Modifiers in C#

Step 3: Create another console application and reference the assembly file from ConsoleApp1. Click on Add Reference in the image below and browse to the location of the .dll file from step 2. It must be similar to ~/ConsoleApp1/bin/Debug/ConsoleApp1.dll.

Access Modifiers in C#

After adding the .dll file, you should find it under Assemblies.

Access Modifiers in C#

Step4: Place the below code in ConsoleApp2.

using System;
using ConsoleApp1; //referencing the first assembly
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var parentObj = new Parent();
//not accessible outside the assembly
Console.Write(parentObj.x);
}
}
}

Step5: When you build ConsoleApp2, you will get a compile-time error indicating that ‘x’ from ConsoleApp1 cannot be accessed in other assemblies due to its protection level.

Access Modifiers in C#

5. Protected Internal

This is a combination of both Protected and Internal access modifiers. An important concept to understand here is that Protected Internal means Protected OR Internal. It is a union of both access modifiers. It must never be thought to be an intersection.

So, Internal objects are not accessible outside the assembly, while Protected objects are accessible to any derived class in any assembly. What if I want to protect my object only in other assemblies and not in the same assembly? Simple solution – declare it as protected internal.

Example:

Step 1: Let us modify our ConsoleApp1 to reflect the code below. Notice we have changed the access level of our variable ‘x’ to protected internal.

using System;
namespace ConsoleApp1
{
public class Parent
{
protected internal int x;
public Parent()
{
x = 10;
}
}
public class Program
{
public static void Main()
{
var parentObj = new Parent();
// accessible within the same assembly
Console.Write("The value of x = " + parentObj.x);
}
}
}

Step 2: Build the solution again and replace the .dll in ConsoleApp2 with the updated one.

Step 3: Update the code in ConsoleApp2 as below:

using System;
using ConsoleApp1; //referencing the first assembly
namespace ConsoleApp2
{
class Program: Parent
{
static void Main(string[] args)
{
var progObj = new Program();
//accessible only via an object of the derived class.
Console.Write(progObj.x);
Console.Read();
}
}
}

Step 4: Run ConsoleApp2 to see the output.

Access Modifiers in C#

6. Private Protected

This is a union combination of both Private and Protected access modifiers. Protected Internal means Protected OR Internal. So, Private objects are not accessible outside the code block in which it is declared, while Protected objects are accessible to any derived class in any assembly. What if I want to restrict my object’s access even in derived classes in other assemblies? Simple solution – declare it as protected internal.

Example:

Let us modify the access level of ‘x’ in ConsoleApp1 to Private Protected.

using System;
namespace ConsoleApp1
{
public class Parent
{
private protected int x;
public Parent()
{
x = 10;
}
}
public class Child: Parent {
public void DisplayX() {
// accessible only via derived class objects
Console.Write("Value of x = " + x);
}
}
public class Program
{
public static void Main()
{
var childObj = new Child();
childObj.DisplayX();
Console.Read();
}
}
}

Output:

Access Modifiers in C#

Tabular Comparison

Following is a tabular comparison of Access Modifiers in C#:

Access Specifier Same Assembly Other Assembly
Same Class Derived Class Non-Derived Class Derived Class Non-Derived Class
Private Yes No No No No
Public Yes Yes Yes Yes Yes
Protected Yes Yes No Yes No
Internal Yes Yes Yes No No
Protected Internal Yes Yes Yes Yes No
Private Protected Yes Yes No No No

Conclusion

We have seen in the above article that access modifiers control the access of everything in the project. Various combinations of access levels cover the needs of various kinds of accessibility. The developers must choose wisely, keeping in mind the security and the absolute necessity of the object to be accessible in a certain block of code.

The above is the detailed content of Access Modifiers in C#. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:Abstract Class in C#Next article:Abstract Class in C#