C# Keywords Tutorial Part 47: internal

C# Keywords Tutorial Part 47: internal

C# is a contemporary, object-oriented programming language that finds wide use in software development such as in applications, websites, and other software solutions. An essential concept in C# is access modifiers, which regulate the visibility and accessibility level of classes, methods, and properties. In this post, we will investigate the “internal” keyword, which is one of the access modifiers in C#.

The “internal” keyword specifies that a class, method, or property is exclusively accessible within the same assembly or module. An assembly is a logical unit of code represented typically by a single file, while a module is a smaller code unit within an assembly. In summary, any code that is part of the same assembly or module as the “internal” element can access it, while code outside of those assemblies or modules cannot.

Let’s take a look at some examples to see how the “internal” keyword works in practice. First, we will create a new C# console application in Visual Studio and add two classes to it, one with an “internal” method and one without:

// MyClass.cs

using System;

namespace MyNamespace
{
    internal class MyClass
    {
        internal void MyMethod()
        {
            Console.WriteLine("MyMethod called");
        }
    }
}

// Program.cs

using System;

namespace MyNamespace
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
            myClass.MyMethod(); // This line will compile
        }
    }
}

In the example given above, we have introduced a class named MyClass that includes an internal method called MyMethod. Additionally, we have also defined a separate class known as Program that comprises the Main method. Within the Main method, we establish an instance of MyClass and invoke its MyMethod method. Since both classes are constituents of the same assembly, this code executes without any complications once compiled.

Now, let’s modify the code slightly by moving the Program class to a separate assembly:

// MyClass.cs

using System;

namespace MyNamespace
{
    internal class MyClass
    {
        internal void MyMethod()
        {
            Console.WriteLine("MyMethod called");
        }
    }
}

// Program.cs (in a separate assembly)

using System;
using MyNamespace;

namespace MyOtherNamespace
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
            myClass.MyMethod(); // This line will not compile
        }
    }
}

In this modified example, we have moved the Program class to a separate assembly and added a using directive for the MyNamespace namespace, which contains the MyClass class. However, when we try to create an instance of MyClass and call its MyMethod method, we get a compilation error because the method is marked as “internal” and is not accessible outside of the MyNamespace assembly.

In order to enable compilation of the code, we could alter the access modifier of the MyMethod method to “public” rather than “internal,” or we could relocate the Program class to the same assembly as MyClass. Another option is to use the “InternalsVisibleTo” attribute, which permits the Program class to access the internal constituents of the MyNamespace assembly.

// MyClass.cs

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("MyOtherNamespace")]

namespace MyNamespace
{
    internal class MyClass
    {
        internal void MyMethod()
        {
            Console.WriteLine("MyMethod called");
        }
    }
}

// Program.cs (in a separate assembly)

using System;
using MyNamespace;

namespace MyOtherNamespace
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
			myClass.MyMethod(); // This line will compile now
		}
	}
}

In this last example, we appended the “InternalsVisibleTo” attribute to the MyClass.cs file, which specifies that the MyOtherNamespace assembly can access the internal constituents of the MyNamespace assembly. Consequently, we can create an instance of MyClass and invoke its MyMethod method from the Program class, even though they exist in separate assemblies.

Share this post

Leave a Reply

Your email address will not be published. Required fields are marked *