-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
private
and namespace
accessibility modifiers for top-level types
- Proposed
- Prototype: Not Started
- Implementation: Not Started
- Specification: Not Started
Summary
[summary]: Enable the private
modifier to be used for top level types in C#. The semantics of this would differ from internal
in that while internal
means "this assembly and any assemblies with IVT to this", private
would mean "this assembly only". This is already the meaning for nested types, but is not available for top level types.
Similarly, enable the namespace
modifier to be used for types in c#. The semantics of this are that these types are only accessible within that namespace
only (not including sub-namespaces).
Motivation
[motivation]: Currently, based on the v1 rules of the language, the narrowest accessibility a top-level-type (i.e. one directly in a namespace) can get is internal
. This was fine in v1 as that meant "within this assembly only". Later, this was found to be problematic for components (including Roslyn, the BCL, 3rd parties) that wish to keep things non-public, but which want to share some types across assemblies. To that end, we added the InternalsVisibleTo (IVT) attribute to allow these types to be seeing by a particular clique of assemblies.
This came with a downside though. Using IVT opens up your entire space of internal types to all these assemblies, even if it is only wanted/desirable for a narrow subset of those types. It also makes it more difficult to know what portion of your symbols actually are actually intended for use in these downstream assemblies, and what just got pulled in because there was no way to be excluded.
For tooling, this also makes things more expensive. For example, in the IDE, tools like 'find refs' have to figure out the set of domains they need to look for something in. Once IVT is involved in a project, then effectively all top level symbols have to be looked for in those larger cliques. Being able to explicitly make types exist only in a single assembly can greatly improve performance.
Similar issues exist for things like ref-assemblies. Right now they must include internal types (if IVT) is on, and will be updated whenever any of those change (even if there is no intent or usage of those types downstream). Having these types truly be 'private' (and thus not included in these artifacts), limits the surface area, and makes more changes less impactful downstream.
Detailed design
Allow private
as a modifier for top-level-types. These types would only be visible within that assembly, including when the IVT attribute was present.
Similar to how accessibility is checked today, a private-type could not be exposed by some type/member taht itself was exposed beyond the assembly. For example, it could not be the base-type of an internal type, or a parameter/return type of some internal visible member.
Drawbacks
- This definitely makes the language more complex.
- This would likely push for codebases to now switch over to 'private' by default.
- For back compat reasons, we'd likely have to make it so that a type without accessibility still defaulted to
internal
.