Published on

Access modifiers

image
Authors
  • avatar
    Name
    David Jimenez
    Twitter

Access modifiers control whether a type or one of its properties can be used by other code. The C# language, at time of writing, has six access modifiers: public, private, protected, internal, protected internal, and private protected. Of these, the first two, public and private, are the most common. public is used with interfaces, classes, and properties; private is used with backing fields and ocassionally with methods.

Defaulting to public for interfaces makes sense since they represent a contract. Equally, Defaulting to private for backing fields makes sense since those should be accessed and modified only the containing class. However, making most classes public seems like a missed opportunity.

Let's imagine the scenario where you are building a class library. You have a number of interfaces, and their implementations. Everything is public. A user of your library can simply instantiate one of your classes. The class implements an interface, but it also has additional public methods that the user can start to rely on. If you then change the class, and modify or remove those methods not covered by the interface, then the user's code will break.

One possible reason why public has become the default is because of testing. In order to test a class we have to make it available to the testing project. However, there is an alternative: friend assemblies. That is, we can make our classes internal, and specify which other projects can access those internal types.

The way to specify the friend assembly is to use the attribute InternalsVisibleTo. The argument is the name of the assembly we are sharing the code with.

using System.Runtime.CompilerServices;
using System;
 
[assembly: InternalsVisibleTo("AssemblyWithTests")]
internal class TargetClass 
{
    public void TargetMethod()
    {
        Console.WriteLine("Hello World");
    }
}

For more information about friend assemblies, check out the Microsoft documentation: https://learn.microsoft.com/en-us/dotnet/standard/assembly/friend