Exploring C# 10: Save Space with File-Scoped Namespaces
Tags: csharp, dotnet
Published: 2021-10-06 13:14:22

---
title: Exploring C# 10: Save Space with File-Scoped Namespaces
published: true
date: 2021-10-05 03:35:27 UTC
tags: csharp, dotnet
canonical_url: https://www.daveabrock.com/2021/10/05/csharp-10-file-scoped-namespaces/
---

.NET 6 and C# 10 hit general availability [next month](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10) (in November 2021). Much like I did [with C# 9 last year](https://www.daveabrock.com/tag/csharp-9-2/), I'd like to write about C# 10 over my next few posts. First, let's talk about a simple yet powerful capability: file-scoped namespace declarations.

If you're new to C# and aren't familiar with what namespaces are, you can use a `namespace` keyword to declare scopes that contain a set of related objects. What kind of objects? According to [the Microsoft documentation](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/namespace), namespaces can have classes, interfaces, enums, structs, or delegates. By default, the C# compiler adds a default, unnamed namespace for you—typically referred to as the global namespace. When you declare a specific namespace, you can use identifiers present in the global namespace. See [the C# docs](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/namespace) for details.

So, how can you declare namespaces in C# 9 and earlier? Keeping with my superhero theme with [my C# 9 posts](https://www.daveabrock.com/tag/csharp-9-2/), a `Superhero.cs` class would look like this:

```csharp
using System;

namespace SuperheroApp.Models
{
   public class Superhero
   {
      public string? FirstName { get; set; }
      public string? LastName { get; set; }
      public string? StreetAddress { get; set; }
      public string? City { get; set; }
      public int? MaxSpeed { get; set; }
   }
}
```

Even with this simple example, you can see how much space this adds—both horizontally and vertically—with the indents and curly braces. With C# 10, you can make this cleaner with file-scoped namespaces.

## Use C# 10 file-scoped namespaces to simplify your code

With C# 10, you can remove the curlies and replace it with a semicolon, like this:

```csharp
namespace SuperheroApp.Models;

public class Superhero
{
   public string? FirstName { get; set; }
   public string? LastName { get; set; }
   public string? StreetAddress { get; set; }
   public string? City { get; set; }
   public int? MaxSpeed { get; set; }
}
```

If you have `using` statements in your file, you can have the namespace declaration either before or after it. However, it must come before any other members in a file, like your classes or interfaces. Many code analyzers like StyleCop [encourage the use of usings inside namespaces](https://documentation.help/StyleCop/SA1200.html) to avoid type confusion.

It's worth noting that as the "file-scoped" naming implies, this applies to any objects in the file—like classes, interfaces, structs, and so on. Also, you are limited to only defining one file-scoped namespace per file. You likely aren't surprised, as most of your files typically only have a single namespace.

## Limitations with file-scoped namespaces

Now, let's review what you cannot do with file-scoped namespaces.

### Mix traditional namespaces and file-scoped namespaces

If you want to mix a non-C# 10 namespace declaration and a file-scoped namespace, you can't. Here's what you'll see from Visual Studio.

![](https://www.daveabrock.com/content/images/2021/10/image.png)

### Define multiple file-scoped namespaces

What if you want multiple namespaces in a file like this?

```csharp
namespace SuperheroApp.Models;

public class Superhero
{
    public string? FirstName { get; set; }
    public string? LastName { get; set; }
    public string? StreetAddress { get; set; }
    public string? City { get; set; }
    public int? MaxSpeed { get; set; }
}

namespace SuperheroApp.Models.Marvel;

public class MarvelSuperhero : Superhero
{
    public string[] MoviesIn { get; set; }
}
```

As discussed previously, you can only define one file-scoped namespace per file. It won't work.

![](https://www.daveabrock.com/content/images/2021/10/multiple-fs-namespaces-1.png)

If you want to accomplish this, you'll need to stay old school and define namespace declarations as you usually have.

```csharp
namespace SuperheroApp.Models
{
    public class Superhero
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public string? StreetAddress { get; set; }
        public string? City { get; set; }
        public int? MaxSpeed { get; set; }
    }
}

namespace SuperheroApp.Models.Marvel
{
    public class MarvelSuperhero : Superhero
    {
        public string[] MoviesIn { get; set; }
    }
}
```

### Nesting namespaces

With traditional namespaces, you can nest them like in the following example.

```csharp
namespace SuperheroApp.Models
{
    public class Superhero
    {
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public string? StreetAddress { get; set; }
        public string? City { get; set; }
        public int? MaxSpeed { get; set; }
    }

    namespace SuperheroApp.Models.Marvel
    {
        public class MarvelSuperhero : Superhero
        {
            public string[] MoviesIn { get; set; }
        }
    }
}
```

However, you can not do this with file-scoped namespaces. When I try to do this, I'll get another compiler error.

![](https://www.daveabrock.com/content/images/2021/10/nested-namespaces.png)

## Wrapping up: another way to simplify C# code

If you've been following the last couple of C# releases, you've noticed this isn't the first change to simplify boilerplate code—see positional C# records and top-level statements for a few examples—and it likely won't be the last, either. Changes like this allow you to simplify your programs and cut out boilerplate.

In the next post, I'll continue this theme by writing about [global using directives](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10#global-using-directives) in C# 10. I'll talk to you then.