C# tutorials > Modern C# Features > C# 6.0 and Later > What are file-local types?
What are file-local types?
File-local types in C# (introduced in C# 11) provide a way to restrict the visibility of a type (class, struct, interface, enum, or delegate) to the file in which it's declared. This is done using the They are a powerful tool for encapsulation and can help reduce naming conflicts, especially in large projects or when generating code. Think of them as a more granular version of file
modifier.internal
, limiting scope to a single file rather than an entire assembly.
Basic Syntax
The file
keyword is placed before the type declaration (class
, struct
, interface
, enum
, or delegate
). This indicates that MyFileLocalClass
is only accessible within the file it is defined in. Outside of this file, it's as if the class doesn't exist.
file class MyFileLocalClass
{
public void DoSomething()
{
Console.WriteLine("Doing something in MyFileLocalClass.");
}
}
Example Usage
In the MyFile.cs
example, MyFileLocalClass
is declared with the file
modifier. Inside the same file, MyOtherClass
can instantiate and use MyFileLocalClass
without any issues. However, in AnotherFile.cs
, attempting to create an instance of MyFileLocalClass
results in a compile-time error because it's outside the defined scope of the type.
// File: MyFile.cs
file class MyFileLocalClass
{
public void DoSomething()
{
Console.WriteLine("Doing something in MyFileLocalClass.");
}
}
public class MyOtherClass
{
public void UseFileLocal()
{
var instance = new MyFileLocalClass(); // This is OK because it's in the same file
instance.DoSomething();
}
}
// File: AnotherFile.cs
// The following code will cause a compile-time error
// because MyFileLocalClass is not accessible in this file.
//MyFileLocalClass anotherInstance = new MyFileLocalClass(); // Error: MyFileLocalClass is inaccessible due to its protection level
Concepts Behind the Snippet
The core concept here is encapsulation. File-local types allow you to hide implementation details within a single file. This reduces the chances of naming conflicts and makes the code more maintainable by preventing accidental dependencies on internal types from other parts of your project. They improve code modularity by promoting isolated units of code within a file.
Real-Life Use Case Section
Consider a code generation scenario where you generate helper classes or structs specific to a particular process within a single file. Using file-local types prevents these generated types from interfering with other parts of the codebase. Another use case is in implementing complex algorithms or data structures where you want to define internal helper types that are only relevant within that specific implementation. Imagine a parser that needs internal structures for processing; making them file-local prevents these structures from polluting the global namespace.
Best Practices
internal
and file
accessibility, choose file
if the type is only needed within a single file.
Interview Tip
Be prepared to explain the difference between file
, internal
, protected
, public
, and private
access modifiers. Also, be ready to discuss the benefits of encapsulation and how file-local types contribute to it. A good understanding of these concepts demonstrates your ability to write clean, maintainable, and robust code.
When to Use Them
Use file-local types when you need to create a type that should only be accessible within a single file. This is particularly useful for helper classes, structs, or enums that are specific to a particular implementation within that file. They are not useful when you intend to reuse that specific type across different classes or files, in that case, you should use internal
, or even expose the type publicly if it is part of the intended public API.
Memory Footprint
File-local types do not inherently have a different memory footprint compared to other types. The memory usage is determined by the data members of the type, not its accessibility modifier. The file
modifier primarily impacts compile-time visibility, not runtime behavior or memory allocation.
Alternatives
Before C# 11, you would typically use private
or internal
accessibility to achieve a similar effect. However, private
limits visibility to the enclosing type, while internal
exposes the type to the entire assembly. File-local types offer a more precise level of control when you want to restrict visibility to a single file. Another alternative is to use nested classes within the class needing the helper, making them private to the enclosing type but they will belong logically to that same class and not be reusable in other classes of the file.
Pros
Cons
file
modifier may be confused by the limited accessibility of these types.
FAQ
-
Can I use file-local types in interfaces?
Yes, you can declare interfaces as file-local using thefile
modifier. -
Can I use file-local types as return types or parameters in public methods?
No, you cannot expose file-local types in public APIs because that would violate the principle of encapsulation and lead to compile-time errors when the API is consumed from outside the file. -
What happens if I have two files with the same file-local type name?
Each file will have its own distinct type with that name. They are treated as completely separate types by the compiler. There will be no naming conflict because their scope is limited to their respective files. -
Is the `file` modifier valid for other members besides types?
No, the `file` modifier is exclusively for types (classes, structs, interfaces, enums, and delegates).