Skip to content

[Proposal]: Add private and namespace accessibility modifiers for top-level types. #6794

@CyrusNajmabadi

Description

@CyrusNajmabadi

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

  1. This definitely makes the language more complex.
  2. This would likely push for codebases to now switch over to 'private' by default.
  3. For back compat reasons, we'd likely have to make it so that a type without accessibility still defaulted to internal.

Design meetings

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions