[Proposal]: Add private
and namespace
accessibility modifiers for top-level types.
#8654
Replies: 79 comments 1 reply
-
Does the runtime already support this or is there an implied runtime change dependency? |
Beta Was this translation helpful? Give feedback.
-
private class C1
{
}
internal class C2
{
internal void M(C1 c1) { }
} I'd like to be able to call |
Beta Was this translation helpful? Give feedback.
-
Make M private, or make C1 internal. Right now this is the IVT problem. you're exposing MS to everything in IVT. Unclear if we have have a middle ground for members that says "internal, but only to this assembly". |
Beta Was this translation helpful? Give feedback.
-
@RikkiGibson To me, that example says that since a new kind of accessibility is being added, it needs a new keyword, that can then be used everywhere. And |
Beta Was this translation helpful? Give feedback.
-
I feel it seems a bit difficult to teach beginners the difference between private and intenal, because there are not so many opportunities for beginners to use IVT attributes. |
Beta Was this translation helpful? Give feedback.
-
I imagine you wouldn't teach beginners this. |
Beta Was this translation helpful? Give feedback.
-
Isn't the |
Beta Was this translation helpful? Give feedback.
-
Why would this not be taught? It may not be a beginner topic, but that hardly relevant here. |
Beta Was this translation helpful? Give feedback.
-
Even now, people try to put private on top-level types mistaking it for internal. I think that if we introduce the private modifier, people will use private unintentionally and without worrying about the difference between it and internal. My concern is that private - a common word - is associated with IVT - a less familiar feature. |
Beta Was this translation helpful? Give feedback.
-
would I see some positives here if that is the case, although it might lead to people doing things they really shouldn't and creating fragile code when another assembly pushes a new version. |
Beta Was this translation helpful? Give feedback.
-
Why would that be a problem? If they're not using ivt it won't matter. If they are using ivt, then private will still be a good choice for limited visibility. And if they actually need to expose the type to one of their other assemblies, they can make it internal. |
Beta Was this translation helpful? Give feedback.
-
No. This would be within an assembly. |
Beta Was this translation helpful? Give feedback.
-
These days, C# tends to make the most recommended style the easiest to write. If you want to encourage people to use |
Beta Was this translation helpful? Give feedback.
-
I have no dog in the race about encouragement. I think people should use whatever pattern makes sense for their codebase. If people want to make their types private, because that fits their goals better, then i'm all for that. If they want to keep them internal, i'm also fine with that. What i care most about is that those who do want to use IVT, but not expose as much, have an option to help themselves out here :) |
Beta Was this translation helpful? Give feedback.
-
Making what sealed? |
Beta Was this translation helpful? Give feedback.
-
And My point is that it feels like adding more accessibility levels here feels like a very big hammer to address something experienced by an extreme minority of the developer audience. |
Beta Was this translation helpful? Give feedback.
-
@FaustVX that's what this proposal is ... Finding a way to allow ivt, without exposing everything. I feel like people are way too caught up on Syntax. |
Beta Was this translation helpful? Give feedback.
-
To reiterate, this proposal is about a way to more narrowly expose types to other assemblies. The private keyword is strawman Syntax for that. Just like my other proposal is about scoping typesinside an assembly (with strawman around that). The fundamental goal is better control around the scoping of the type, since all we have is internal today. That's both too broad within, and too broad without. |
Beta Was this translation helpful? Give feedback.
-
That's fair. I think it's worth exploring if there are non-language ways to accomplish that, especially given that IVT is already a non-language mechanism for expanding accessibility, and if that mechanism offered more flexibility that could satisfy the use cases without requiring language changes. Internally, maybe it'd be more interesting to talk about adding modules to C# that are independent of namespaces, and types/members can have module accessibility within the module. Of course all of that could be defined via custom attributes and analyzers also. |
Beta Was this translation helpful? Give feedback.
-
I'm def interested. The reason i went with |
Beta Was this translation helpful? Give feedback.
-
You can use |
Beta Was this translation helpful? Give feedback.
-
What would be nice is: public class ClassB { The Friend attribute would be the same as private/protected + allow any classes within the friend group to access. Namespace is just a convenient way to declare a group of classes that all have special access to each other. This would be a lot simpler to implement, I would think. |
Beta Was this translation helpful? Give feedback.
-
You could accomplish this today with |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Does this include hiding methods from other classes in the same assembly (that are not friends)? |
Beta Was this translation helpful? Give feedback.
-
Here's an analyzer that claims to have this capability: https://github.com/piotrstenke/Durian |
Beta Was this translation helpful? Give feedback.
-
Java modules and packages, with related accessibility rules, are THE features where Java trumps C#, IMHO. C# already has a lot of accessibility modifiers and none solve problems that people (included me) actually have, and that is "friendship" which use-cases have been elaborated elsewhere. In a green-field project it's possible to split functionality across assemblies so that For my part I often wanted
[1] Use-case example: the namespace defines a tree framework, and predefines a So And the more I think about accessibility rules in C#, the more I wonder about why namespaces exist at all. The reason for me (still) using namespaces are
The mentioned scenario about trees could be emulated as
and then in another assembly:
The only thing that feels "iffy" about it is that it significantly deviates from C# code one sees "out in the wild", including BCL, i.e., it uses class as namespace with enhanced access control. With classes, one might run into issues with lack of MI, but one could just as well use And then we have
As of today, |
Beta Was this translation helpful? Give feedback.
-
I am just here to say I wish this already existed. To me it seems really straight forward to just having them be I manage very large projects that use source generators and those source generators add marker attributes. This attributes conflict with each other when you have IVT. The project still compile but the warnings never go away, unless you suppress them. |
Beta Was this translation helpful? Give feedback.
-
I had a use for it just last week. |
Beta Was this translation helpful? Give feedback.
-
Wishing for this for a long time :) |
Beta Was this translation helpful? Give feedback.
-
I belive custom Roslyn analizer can be created for this and can be pluged in using nuget/mabuild. So you have internal visibilty + some attribute to place on mambers to be hidden. And it would throw compile time error if used improperly. You could restrict not to namespace but to friend classes in C++ way. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
private
andnamespace
accessibility modifiers for top-level typesSummary
[summary]: Enable the
private
modifier to be used for top level types in C#. The semantics of this would differ frominternal
in that whileinternal
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 thatnamespace
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
internal
.Beta Was this translation helpful? Give feedback.
All reactions