C# Specifiers Explained: What You Need to Know

Fırat TONAKFırat TONAK
4 min read

In this article, we will learn about specifiers and how to use them. They are important for managing your code securely and maintaining a strong structure in terms of architecture and code quality. Additionally, this topic is fundamental for Object-Oriented Programming (OOP).

We use specifiers to manage the accessibility of our classes and methods. There are four different types of specifiers: public, private, protected, internal, and protected internal.

Public Specifier

The public specifier is accessible at all levels of the project.

An important point is that the public specifier can also be accessed by other assemblies when your DLL is referenced.

Product.cs

namespace Specifiers;

public class Product
{
    private string? _productName;
    public string? ProductName
    {
        get { return _productName; }
        set { _productName = value; }
    }
    public string GetProductName()
    {
        return ProductName ?? "";
    }
}

Program.cs

Product newProduct = new Product();
newProduct.ProductName = "Test Product";
newProduct.GetProductName();

As you can see, we can access the public methods and fields anywhere in the project.

Private Specifier

The private specifier is accessible only within the class where it is defined.

The private specifier cannot be accessed by other assemblies, even when your DLL is referenced.

Product.cs

namespace Specifiers;

public class Product
{
    private string? _productName;
    public string? ProductName
    {
        get { return _productName; }
        set { _productName = value; }
    }
    public string GetProductName()
    {
        if (!IsProductAvailable())
        {
        return "Product is not available";
        }
        return ProductName ?? "";
    }

    private bool IsProductAvailable()
    {
        return false;
    }
}

As you can see, we cannot access the private method in Program.cs. However, we can access the private method in Product.cs

Protected Specifier

The protected specifier can be accessed within the same class and in derived classes.

If your derived class is in another assembly, your protected methods are still accessible.

Product.cs

namespace Specifiers;

public class Product
{
    private string? _productName;
    public string? ProductName
    {
        get { return _productName; }
        set { _productName = value; }
    }

    private decimal? _productPrice;
    public decimal? ProductPrice
    {
        get { return _productPrice; }
        set { _productPrice = value; }
    }

    private bool? _productStatus;
    public bool? ProductStatus
    {
        get { return _productStatus; }
        set { _productStatus = value; }
    }
    public string GetProductName()
    {
        if (!CheckProductIsAvailable())
        {
        return "Product is not available";
        }
        return ProductName ?? "";
    }

    private bool IsProductAvailable()
    {
        return false;
    }

    protected bool? GetProductStatus()
    {
        return _productStatus;
    }
}

As you can see, we cannot access the GetProductStatus method in the Program.cs file.

However, when I make the Product.cs class abstract, we can access the protected methods in the derived class.

Product.cs

namespace Specifiers;

public abstract class Product
{
    private string? _productName;
    public string? ProductName
    {
        get { return _productName; }
        set { _productName = value; }
    }

    private decimal? _productPrice;
    public decimal? ProductPrice
    {
        get { return _productPrice; }
        set { _productPrice = value; }
    }

    private bool? _productStatus;
    public bool? ProductStatus
    {
        get { return _productStatus; }
        set { _productStatus = value; }
    }
    public string GetProductName()
    {
        if (!IsProductAvailable())
        {
        return "Product is not available";
        }
        return ProductName ?? "";
    }

    private bool IsProductAvailable()
    {
        return false;
    }

    protected virtual bool? GetProductStatus()
    {
        return _productStatus;
    }
}

Computer.cs

namespace Specifiers;

public class Computer : Product
{
    protected override bool? GetProductStatus()
    {
    return base.GetProductStatus();
    }
}

Internal Specifier

The internal specifier can be accessed anywhere within the project.

The internal specifier cannot be accessed by other assemblies, even when your DLL is referenced.

Product.cs

namespace Specifiers;

public abstract class Product
{
    private string? _productName;
    public string? ProductName
    {
        get { return _productName; }
        set { _productName = value; }
    }

    private decimal? _productPrice;
    public decimal? ProductPrice
    {
        get { return _productPrice; }
        set { _productPrice = value; }
    }

    private bool? _productStatus;
    public bool? ProductStatus
    {
        get { return _productStatus; }
        set { _productStatus = value; }
    }
    public string GetProductName()
    {
        if (!IsProductAvailable())
        {
        return "Product is not available";
        }
        return ProductName ?? "";
    }

    private bool IsProductAvailable()
    {
        return false;
    }

    protected virtual bool? GetProductStatus()
    {
        return _productStatus;
    }

    internal decimal? GetProductPrice()
    {
        return ProductPrice ?? 0;
    }

}

Program.cs

using Specifiers;

Product computer = new Computer();
computer.ProductPrice = 150;
computer.GetProductPrice();

ProtectedInternal Specifier

The protectedInternal specifier is accessible at all levels within the project, as well as by other assemblies when your DLL is referenced.

If your derived class is in another assembly, your protectedInternal methods are accessible.

I have tried to explain the different types of specifiers in C# and why they are needed.

I did not include an example of the protectedInternal specifier because it is very similar to the public specifier. The only difference is that while the public specifier is accessible everywhere, including in other assemblies and external code, the protectedInternal specifier cannot be accessed by external code in other assemblies."

You can reach the code here

0
Subscribe to my newsletter

Read articles from Fırat TONAK directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Fırat TONAK
Fırat TONAK