.NET Assemblies
C#
.NET Framework
Software Development
Programming

What are .NET Assemblies?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A .NET assembly is the compiled unit that the .NET runtime loads and executes. When you build a C# project, the result is usually an .exe or .dll file, and that output is an assembly.

Why Assemblies Matter

Assemblies are more than simple containers for compiled code. They define the boundary for deployment, versioning, metadata, and type identity in .NET.

An assembly typically contains:

  • Intermediate Language, often called IL,
  • metadata describing types and references,
  • an assembly manifest,
  • optional embedded resources such as strings or images.

The runtime uses that information to locate dependencies, check versions, load types, and enforce visibility rules.

The Manifest and Metadata

The manifest is the assembly's identity card. It records details such as:

  • assembly name,
  • version,
  • culture,
  • referenced assemblies,
  • strong-name information when present.

Metadata describes the actual types inside the assembly: classes, methods, properties, fields, and attributes. That is why reflection works so well in .NET. The runtime does not need separate header files because type information travels with the compiled output.

You can inspect assembly information at runtime with reflection:

csharp
1using System;
2using System.Reflection;
3
4class Program
5{
6    static void Main()
7    {
8        Assembly assembly = typeof(string).Assembly;
9        Console.WriteLine(assembly.FullName);
10        foreach (Type type in assembly.GetExportedTypes())
11        {
12            Console.WriteLine(type.FullName);
13            break;
14        }
15    }
16}

This example prints the identity of the assembly that contains System.String and shows that types can be discovered dynamically.

Assemblies, Projects, and Namespaces

Developers often confuse assemblies with namespaces, but they solve different problems.

  • A namespace is a logical naming structure for code organization.
  • An assembly is the compiled deployment unit.

One assembly can contain many namespaces, and one namespace can be spread across multiple assemblies.

Likewise, a Visual Studio project often produces one assembly, but that is a build convention, not the definition of the term.

dll Versus exe

Both .dll and .exe files can be assemblies. The difference is usually whether the assembly has an entry point.

  • An executable assembly has a Main method and can be launched directly.
  • A library assembly exposes code for other assemblies to use.

From the runtime's point of view, both carry IL, metadata, and manifest information.

Private and Shared Assemblies

Historically, .NET Framework documentation often distinguishes between private and shared assemblies.

  • A private assembly is deployed alongside one application.
  • A shared assembly is designed to be reused by multiple applications.

In older .NET Framework environments, shared assemblies might be installed into the Global Assembly Cache, or GAC, and often strong-named. In modern .NET, application-local deployment is usually more common than machine-wide installation.

Simple Example: Building a Library Assembly

Suppose you create a class library like this:

csharp
1namespace MathTools
2{
3    public class Calculator
4    {
5        public int Add(int left, int right) => left + right;
6    }
7}

When you build the project, the compiler produces a .dll assembly. Another application can reference that assembly and use the Calculator type.

csharp
1using System;
2using MathTools;
3
4class Program
5{
6    static void Main()
7    {
8        var calculator = new Calculator();
9        Console.WriteLine(calculator.Add(2, 3));
10    }
11}

The reference works because the consuming assembly can read the producer assembly's metadata and locate the public type.

Why Assemblies Enable Versioning

Assemblies make versioning explicit. The manifest can declare version numbers and referenced dependencies, which helps the runtime decide what to load.

That does not eliminate dependency problems, but it is a major part of how .NET manages type identity. Two types with the same namespace and name are not considered the same if they come from different assemblies.

Common Pitfalls

The most common mistake is treating namespaces and assemblies as interchangeable terms. They are related, but they are not the same thing.

Another issue is assuming a .dll is merely a bag of code with no runtime meaning. In .NET, the assembly carries manifest and metadata that the runtime actively uses.

Developers also forget that assembly identity includes more than the filename. Version, culture, and signing information can all matter for loading and compatibility.

Summary

  • A .NET assembly is the compiled unit the runtime loads, usually an .exe or .dll.
  • It contains IL, metadata, and a manifest.
  • Assemblies are the boundary for loading, versioning, and type identity.
  • Namespaces organize code logically, but assemblies are deployment artifacts.
  • Reflection, dependency loading, and library reuse all depend on assembly metadata.

Course illustration
Course illustration

All Rights Reserved.