-
Couldn't load subscription status.
- Fork 1.1k
Description
This is the next turn of the crank on #5529.
Permit a file modifier on top-level type declarations. The type only exists in the file where it is declared.
// File1.cs
namespace NS;
file class Widget
{
}
// File2.cs
namespace NS;
file class Widget // different symbol than the Widget in File1
{
}
// File3.cs
using NS;
var widget = new Widget(); // error: The type or namespace name 'Widget' could not be found.Benefits
Removes the need for users to reason out what combinations of access modifiers are permitted with the file modifier on non-type members. Leaves the design space open for non-type file-scoped members to come along later.
Drawbacks
It may be inconvenient to be unable to declare file-scoped methods, properties, etc., even those with private or internal accessibility. The feature may not be viable for some use cases if it can only be adopted at the type level.
Accessibility
No accessibility modifiers can be used in combination with file on a type.
public file class C1 { } // error
internal file class C2 { } // error
file class C3 { } // okThe implementation guarantees that file types in different files with the same name will be distinct to the runtime. The type's accessibility and name in metadata is implementation-defined. The intention is to permit the compiler to adopt any future access-limitation features in the runtime which are suited to the feature. It's expected that in the initial implementation, an internal accessibility would be used and the name would be mangled based on which file the type is declared in.
Usage in signatures
There is a general need to prevent file types from appearing in member signatures where the file type might not be in scope at the point of usage of the member.
Only allow in members of file types
Perhaps the simplest way to ensure this is to enforce that file types can only appear in signatures or as base types of other file types:
file class FileBase
{
}
public class Derived : FileBase // error
{
private FileBase M2() => new FileBase() // error
}
file class FileDerived : FileBase // ok
{
private FileBase M2() => new FileBase() // ok
}Alternative: allow in members which are only accessible in this file
We may find the above rule is too limiting. In that case, it's also worth considering a rule to instead say that a file scoped type can only appear in a member signature, if that member is only accessible within the same file.
file class Widget
{
}
public class Program
{
private void M1(Widget w) { } // ok
internal void M2(Widget w) { } // error
}
partial class Utils
{
private void M1(Widget w) { } // error
}Implementation/overrides
file scoped type declarations can implement interfaces, override virtual methods, etc. just like regular type declarations.
file struct Widget : IEquatable<Widget>
{
public bool Equals(Widget other) => true;
}