File access modifier

Discovering the file access modifier in C#11

Home DailyDrop

Daily Knowledge Drop

A new access modifier is being introduced with C#11, the file modifier - this will limit the accessibility of the type to the file in which it is declared.


Modifier recap

A quick recap of the existing access modifiers, along with the new file modifier (as they relate to classes).

Existing modifiers:

  • private - the class is only accessible inside the class in which it was defined
  • public - the class is accessible from everywhere in the project
  • protected - the class is accessible from within the class and all types which derive from the class
  • internal - the class is accessible from within its own assembly, but not other assemblies

The new modifier:

  • file - the class is accessible only from within the file in which it was defined

Example

When a class is defined, the file modifier is applied (as opposed to public, private, etc.)

file class Class1
{
    public string Name { get; set; }
}

This class now cannot be used anywhere outside the file in which is was defined. Trying to use in a different class defined in a different file, will result in a compilation error:

public class Class3
{
    public Class3()
    {
        // NOT allowed
        Class1 ca = new Class1();
    }
}
The type or namespace name 'Class1' could not be found

However, as mentioned, it can be used in the same file:

// all in the same physical file
file class Class1
{
    public string Name { get; set; }
}

file class Class2
{
    public Class2()
    {
        // Totally okay
        Class1 c1 = new Class1();
    }
}

The file access modifier can be applied to classes, records, structs and enums, but cannot be used for methods or properties.


Why?

This functionality was primarily introduced to assist source generator authors. When a source generator generates a class, its tricky to ensure it's not going to conflict with a file already in the consumer's code base. The file modifier helps solves this by ensuring (where specified) the the source generated file is only visible where defined, and not in conflict with any developer specified class name.


Lowered code

One can use sharplab.io to see how the file keyword is lowered:

Original code:

file class FileScopedClass { }

Lowered code:

internal class <_>FD2E2ADF7177B7A8AFDDBC12D1634CF23EA1A71020F6A1308070A16400FB68FDE__FileScopedClass { }

From this we can see that the file keyword is translated into an internal class with a uniquely generated name, as to not conflict with any existing name


Notes

While the intended target audience for this feature is very narrow (source generator authors), it can be leveraged by anyone if the use case calls for it. Even then, it may not get wide usage in general applications - however it is useful to know it exists and is an option if required.


References

What is the NEW "file" keyword of C# 11?

Daily Drop 189: 25-10-2022

At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.

The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.
c# .net .net7 filemodifier