The file modifier

Beginning with C# 11, the file contextual keyword is a type modifier.

The file modifier restricts a top-level type's visibility to the file in which it's declared. The file modifier is most often applied to types written by a source generator. File-local types provide source generators with a convenient way to avoid name collisions among generated types. The file modifier declares a file-local type, as in this example:

file class HiddenWidget
{
    // implementation
}

Any types nested within a file-local type are also only visible within the file in which it's declared. Other types in an assembly can use the same name as a file-local type. Because the file-local type is visible only in the file where it's declared, these types don't create a naming collision.

A file-local type can't be the return type or parameter type of any member declared in a non file-local type. A file-local type can't be a field member of a non-file-local. However, a more visible type can implicitly implement a file-local interface type. The type can also explicitly implement a file-local interface but explicit implementations can only be used within the same file.

The following example shows a public type that uses a file-local type to provide a worker method. In addition, the public type implements a file-local interface implicitly:

// In File1.cs:
file interface IWidget
{
    int ProvideAnswer();
}

file class HiddenWidget
{
    public int Work() => 42;
}

public class Widget : IWidget
{
    public int ProvideAnswer()
    {
        var worker = new HiddenWidget();
        return worker.Work();
    }
}

In another source file, you can declare types that have the same names as the file-local types. The file-local types aren't visible:

// In File2.cs:
// Doesn't conflict with HiddenWidget
// declared in File1.cs
public class HiddenWidget
{
    public void RunTask()
    {
        // omitted
    }
}

Member lookup prefers a file-local type declared in the same file over a non-file-local type declared in a different file. This rule ensures that a source generator can rely on member lookup resolving to a file-local type without ambiguity with other type declarations. In the preceding example, all uses of HiddenWidget in File1.cs resolve to the file-local type declared in File1.cs. The file-local declaration of HiddenWidget hides the public declaration in File2.cs.

C# language specification

For more information, see Declared accessibility in the C# Language Specification, and the C# 11 - File local types feature specification.

See also