-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
File-local types #6011
Comments
One important follow-up question is: what happens when a A major point of the feature is about avoiding name conflicts. In that spirit, it seems like it should be allowed for a // File1.cs
namespace NS;
class Widget { }
// File2.cs
namespace NS;
file class Widget { } // ok. separate from the symbol in File1 // File1.cs
namespace NS;
class Widget { }
file class Widget { } // error: a type with the same name is already declared in this file. |
Would it make sense to extend this to members as a general accessibility type? A use-case I can think of is in types such as However, that
namespace System.IO.Compression;
public partial class ZipArchiveEntry
{
// ...
}
namespace System.IO.Compression;
public partial class ZipArchiveEntry
{
file ZipArchiveEntry(ZipArchive archive, ZipCentralDirectoryFileHeader cd)
{
// ...
}
}
public class ZipArchive : IDisposable
{
// ...
} |
I think we would like to grow it into applying to members eventually. Here are some complications we found:
|
Renaming to "file types" because we felt "file-scoped types" sounded too much like "file-scoped namespaces". |
We will probably rename again to "file-local" types after internal discussion, since we felt "file types" was not specific enough 😄 |
Doing a lot of work to not say "fileprivate access modifier"? Every time I hear "file types" it sounds like something about IO and I know it isn't. 😅 |
Yes, we are 😄. We think this feature is doing stuff that goes beyond just the concept of accessibility, particularly when it comes to shadowing and name conflicts. I see that there are several 👎 on the issue. It would be great to know any specific concerns you have. Is it the terminology in use? or maybe the limitations of the feature as specified here? or something else? Thanks. |
IMO that's an implementation detail. private on a base class allows shadowing too، doesn't make it beyond a accessibility modifier. Regardless, I couldn't figure WHY it's limited to types? And is it intentional that there's no example of "file partial class"? (I'd imagine that's a base usage scenario) All in all, I think it would be actually a lot simpler to look at this as just another accessibility modifier. |
So, this proposal started out being named |
If you consider "file" something less accessible than "private" (or "internal" for top-level types) things will get a lot simpler, with NO combinations allowed. As a user, I wouldn't like to process that many of accessibility levels inside a file. |
Still not supported with .NET 7 RC 1? |
Already supported with .NET 7 Preview 7. |
@ufcpp thanks, I build success with the dotnet cli while got an error with VS, and I'm using the latest vs preview(17.4.0 Preview 2.0) |
@WeihanLi are you using ReSharper? That doesn't look like a roslyn error. |
@333fred yeah, I'm using ReSharper, it does work when I disable the ReSharper, many thanks |
It should be pointed out that the lowering strategy entails surprises for users. A unique class name is generated, but there are cases where class names matter and an unwary developer would expect // This is gonna end up being named <>_generated_Setting at runtime
file class Setting { }
internal static Setting settings;
public void PersistSettings()
{
using var db = new DataContext();
db.Update(settings);
// Expected SQL, table name is inferred from class name:
// UPDATE [Setting] SET ...
} There are work-arounds, for example use case-specific attributes: Maybe a name-preserving strategy would be less surprising, e.g. putting the class in another namespace or class? // In file Models/User.cs
namespace A
{
file class User { }
}
// Generated namespace at build
namespace A.<File>Models_User_cs
{
internal class User { }
}
// Generated class at build
namespace A
{
internal static class <File>Models_User_cs
{
internal class User { }
}
} As an added bonus, the class name would look better in debugger. These are not perfect either, as they may break reflection code that scans specific namespaces, or that doesn't look at nested classes. Maybe those might be less frequent than relying on class name? |
A few thoughts as I have observed feedback and discussion of this feature upon its adoption.
|
Closing this out as the main proposal is #5529. |
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.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
orinternal
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.The 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, aninternal
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 thefile
type might not be in scope at the point of usage of the member.Only allow in members of
file
typesPerhaps the simplest way to ensure this is to enforce that
file
types can only appear in signatures or as base types of otherfile
types: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.Implementation/overrides
file
scoped type declarations can implement interfaces, override virtual methods, etc. just like regular type declarations.The text was updated successfully, but these errors were encountered: