This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET Framework
.NET 1.1+

.NET Assemblies

The seventeenth part of the C# Object-Oriented Programming tutorial considers .NET assemblies. The building blocks of .NET programs, assemblies are the files that contain all of the code, versioning information and resources for an application.


The final section of an assembly holds its resources. Resources include all of the remaining items required by the assembly that are not included in the code. Examples include images, icons, sounds and localised text.

Version Information

DLL Hell

Prior to .NET assemblies, Win32 dynamic linked libraries (DLLs) that contained code used by multiple applications were controlled by the operating system. Each DLL would be registered with Windows but only one version would be accessible at any time. This gave rise to the phrase "DLL Hell", which described the problems that occurred when two programs used the same DLL but required different versions. If the newer version of a DLL were compatible with an older version then both programs would work as expected. However, if the newer version broke the compatibility the older application would fail.

Assembly Versions

.NET assemblies remove the DLL Hell problem by holding their own version information and the name and version for all other, linked assemblies rather than allowing this to be dictated by the operating system. Multiple versions of a DLL may now be installed onto the target computer and the CLR will use a set of rules to determine which version will be used by the executing program.

Assembly Locations

In order for the CLR to identify the correct version of a linked assembly to use, it is allowed to look in three locations. The first location checked is the Global Assembly Cache (GAC). This is a machine-wide repository for assemblies that can be shared by multiple applications.

If the required assembly is not found in the GAC, the location of the application files is checked using a search process called probing. The base folder of the application is tested first, followed by any folder with the same name as the assembly. For example, if the assembly to be found is named "MyAssembly" and the application is installed in the C:\MyProgram folder, the following four paths would be probed:


Assemblies located in the application folder are known as private assemblies. This is because the assembly can only be used by the applications installed in the folder so they cannot be publicly shared. However, because the assembly does not need to be installed in the GAC, entire programs can be installed using simple file copying.

NB: Assemblies can be located in other application sub-folders but the folders must be added to the probing section of the app.config file.

Finally, assemblies can be installed using a CodeBase. This uses an entry in the machine's configuration file to identify a location on a network or FTP site where the assembly can be found and downloaded for its first use.

For each location searched, the CLR will attempt to find an exact match for the required assembly version first. If a perfect match is not found but a range of versions are acceptable, the CLR will attempt to match with other versions before failing.

Internal Access Modifier

When classes are declared as public, they can be utilised by other classes in the same assembly or any other assembly. The internal access modifier changes this behaviour to limit the class's use to other classes within the same assembly. Classes in other assembles are unaware of the presence of items marked as internal.

The internal access modifier can be applied to members of classes such as methods and properties. This allows individual members to be hidden from classes in other assemblies. In this case, a public class from another assembly may be instantiated but only the public members of that class, and not those marked as internal, will be accessible.

public class InternalExample
    public void ThisIsVisibleToOtherAssemblies() { }
    internal void ThisIsInvisibleToOtherAssemblies() { }

NB: If no access modifier is provided when declaring a class, the default visibility is internal.

Protected Internal

The behaviour of the internal access modifier for class members can be changed by using protected internal. Methods and properties marked as protected internal are hidden from other assemblies except where a class is derived from the class in question. For derived classes in other assemblies, internal methods are still hidden but protected internal methods are visible. Inheritance and derived classes are examined in the next instalment of the C# Object Oriented Programming tutorial.

28 February 2008