private protected is an abomination.

Topics: C# Language Design
Apr 4 at 2:03 PM
The consideration to add private protected is an abomination. This is the very definition of violation of the open-closed rule that you would ever need to rely on this. Protected internal by itself is also odd enough but can be justified as a way to DRY code perhaps with a ConvertFoo() method that you want future extenders to have access to and other parts of the assembly would like to use ConvertFoo(). About the only other time I've ever used Protected internal is to allow easy unit testing of private methods via InternalsVisibleTo(test).

One of the most frustrating aspects in .NET with the CLR can be how heavy handed things are in classes that so many types are sealed, so many valuable methods are internal or private, so few methods are virtual. Adding this is just going to be another way the CLR teams can write code to be unfriendly to actually be used.
Apr 4 at 8:05 PM
Edited Apr 4 at 8:08 PM
I am unsure about the usefulness and/or soundness of this accessibility level (I know it exists at the CLR level).

But I had to search what it means, as did those guys:
http://stackoverflow.com/questions/22856215/what-is-the-meaning-of-the-planned-private-protected-c-sharp-access-modifier

I think it's proof that at least the naming is very bad and confusing to even existing C# developers. If you have to do this feature, please reconsider the naming.

In my opinion, it's not a lot more interesting than a plain internal. So for what it's worth, I think you could just as well expose it as an attribute on the field / method (i.e. coders mark the field protected and slaps an InternalOnly attribute on it). That wouldn't be the first time attributes are used to fiddle with internal visibility (I'm thinking of the InternalsVisibleTo assembly attribute).

And on an unrelated note:
Seeing private protected and exception filters, I have a feeling you are trying to align C# with CLR features. If you do, please consider adding try{} fail {} blocks. It's a lot more useful than this one, thanks!
Coordinator
Apr 4 at 9:01 PM
Just curious - what would be the scenario where " try { } fail { } " would be useful?

Note that exception filters do enable specific, although uncommon scenarios that cannot be expressed otherwise - like fast-failing before the stack is unwound and some of the failure context is lost.
The " try{ } fail{ } ", on the other hand, would not seem to be much different from what "try { } catch { }" does already.
Apr 6 at 12:42 PM
Edited Apr 6 at 12:43 PM
I would love to see private protected in the language. However, I also had to look up the semantics; the modifier name not intuitive at all. Unfortunately, I am also unable to come up with a better name at the moment.
Apr 7 at 10:18 AM
@VSadov: try {} fault {} is like a finally but it only executes if you leave the block with an exception. You can emulate it with catch but it can get quickly get tedious.

Consider that you have to run some compensation/logging/whatever if you fail to complete the main logic in your try block. Also consider that your error handling may look like this:
try
{ /* Business logic is here */ }
catch (BusinessError1 e1)
{
  if (e1.Status == 42) return;
  // Otherwise handle e1
}
catch (BusinessError2 e2)
{
  // Handle e2
}
If you want to introduce some compensation logic on every fail path, you must add it at 3 places: in each existing catch block + a new generic catch block that uses throw to re-throw the original exception. This surely warrants a new method to factor out the compensating code, which can be annoying if you need to access local variables.

Another option could be to use finally and a flag set at the end of your try block to know if you completed properly or not. Probably a little bit better, not great either.

Fault is the clean solution to those scenarios:
try
{ /* Business logic is here */ }
catch (BusinessError1 e1)
{
  if (e1.Status == 42) return;
  // Otherwise handle e1
}
catch (BusinessError2 e2)
{
  // Handle e2
}
fault
{ /* Compensation goes here */ }
BTW this is not a brand new feature, the CLR / MSIL already has it. It's useful enough that the C# compiler actually generates this in some cases when compiling iterators (yield).
Apr 7 at 1:30 PM
It took me a few times of reading this to figure out where the try/catch/fault came from (originally seemed like wrong topic). This is something far more valuable to add the fault keyword. There is definitely times where you want code to never fault for any reason and there is alot of hoops you end up jumping through for it.
Apr 7 at 10:32 PM
The naming really sucks.

But that's because protected internal (and internal protected) really stands for protected or internal and there's little to be done to add protected and internal.
Apr 7 at 11:45 PM
Although code should rarely expect to resolve an exception, it should frequently alter its behavior in response to one. For example, if code acquires a write lock and then throws an exception while modifying the guarded object, code shouldn't release the lock as though nothing happened, but nor should it simply leave the lock acquired forever. Instead, code should invalidate the lock, so any pending or future attempts to acquire it will immediately fail. If the thing guarded by the lock will end up getting abandoned during stack unwinding, there's no reason to bring down the whole application. If the thing guarded by the lock was indispensable, the application should be brought down, but the act of invalidating the lock will likely take care of that.

What I'd like to see would be an (Exception Ex) argument to the finally block, as well as a couple of interfaces:

interface IDisposableExOnly { void Dispose(Exception ex); }
interface IDisposableEx : IDisposable, IDisposableExOnly { }

the overload of Dispose which takes an exception would pass null if called for "normal" cleanup, or would pass the exception when called during stack unwinding. A using block should use IDisposableExOnly if implemented, else IDisposable. A class which for proper operation would need code to notify it of exception unwinding could implement IDisposableExOnly without implementing IDisposable to ensure that use by older compilers would yield an error rather than generating code which lacked the proper safeguards.
Developer
Apr 8 at 12:21 AM
Edited Apr 8 at 12:22 AM
If you want to introduce some compensation logic on every fail path, you must add it at 3 places: in each existing catch block + a new generic catch block that uses throw to re-throw the original exception. This surely warrants a new method to factor out the compensating code, which can be annoying if you need to access local variables.
You could also use an exception filter and type check the exception.
Apr 8 at 8:51 AM
I feel bad that my aside about fault seems to have totally hijacked this thread. Maybe we should start a new thread (I can't)?

@angocke: I think you don't understand what fault does. It executes on every exception (like finally), caught or not. Would you care to provide the code equivalent to my example above, but using exception filters instead?
Apr 8 at 7:09 PM
Edited Apr 8 at 7:10 PM
I too am getting the impression that neither @VSadov nor @angocke understand the feature that we are discussing.

This is rather frustrating for us trying to have a conversation with you guys. :( Please consider letting us talk to someone who knows what they are talking about.

As already stated, this topic has hijacked the thread, so... everyone wishing to discuss try/fault, please head over here: https://roslyn.codeplex.com/discussions/541633
Coordinator
Apr 14 at 8:29 PM
private protected is just another accessibility level. It means internal and protected. A lot of people think this is what protected internal already means, and if we could go back and change the language that's what we would have made it mean. But alas, that name is already taken for a much less useful accessibility level that hardly anyone uses.

We have had requests for this feature forever. We had to come up with a syntax. There was no good choice. In the end we went with what we considered the "least bad" combination of two existing keywords. Alternatives were
  • use conjunctives (protected and internal, ...)
  • add new keywords (guarded, hidden, somewhat private, ...)
  • use made-up words (proternal, intected, ...)
  • do nothing
Neither of these seemed appealing. So even though "private protected" doesn't say exactly what it does, it comes close enough and soon enough you'll get used to it. Inherently, most accessibility keywords are pretty meaningless in and of themselves anyway. We just use them enough that we get used to "private" being more restricted than "internal".
Apr 14 at 8:57 PM
Edited Apr 14 at 9:06 PM
private protected is really confusing. You mention a lot of people misinterpret protected internal already. This would make the situation even worse by adding a more bizarrely named operator. Though I definitely think the feature itself is useful.

Personally, I'd prefer having protected and internal and protected or internal both become valid syntax. It doesn't affect existing code, but it allows code to be much more clear going forward. It also makes it easier if there's ever another combination of accessibilities you want to add down the line.

EDIT: I assume the hesitancy with using this syntax was not wanting to add more keywords. I think and and or keywords might be useful in the future in other ways as well. Specifically, generic constraints would be more powerful if you could specify combinations of types with and and or.
Apr 14 at 9:15 PM
I agree. Don't make it any more confusing by adding yet another completely meaningless accessibility modifier (concerning the name; the feature itself is something I'd like to see in the language). With private protected not even the standard way of thinking works anymore: Everything is private by default and you can only add accessibility. The private in private protected adds nothing, especially the internal part is not mentioned anywhere at all. So keeping internal protected for backwards compatibility and adding both protected and internal as well as protected or internal seems to be the better way going forward.
Apr 19 at 7:11 PM
I agree with @MgSam and @Expandable: "protected or internal", "protected and internal" are more reflective of the accessibility these modifiers provide.
Apr 21 at 8:04 AM
Edited Apr 21 at 9:37 AM
I suggest adding two contextual keywords: protectedorinternal and protectedandinternal
Apr 21 at 12:31 PM
protected || internal and protected && internal ? :D
Developer
Apr 21 at 10:57 PM
And since modifiers can appear in any order, you could write

protected static internal && int M() {}
Apr 21 at 11:16 PM
How about protectedinternal?
Apr 22 at 12:20 AM
Edited Apr 22 at 1:01 PM
nmgafter wrote:
And since modifiers can appear in any order, you could write

protected static internal && int M() {}
I'd say that the fact that currently you can split the access modifiers and write
internal async static protected void foo() { }
is already a bit of a misfeature as it makes the method very misleading at a glance to try and ascertain what it is doing. I'd think if adding and and or keywords that you would require they be contextual and only used between access modifiers that support them (protected and internal).

@paulomorgado That would be even more confusing as a single space would denote the difference between internal and protected vs internal or protected.
Apr 22 at 12:58 PM
nmgafter wrote:
And since modifiers can appear in any order, you could write

protected static internal && int M() {}
Well, then just don't allow that by making all of protected or internal the contextual keyword so that it can't be split. Also, your proposed private protected modifier has the same problem: protected static private int M() {} is just as bad.

madst wrote:
Neither of these seemed appealing. So even though "private protected" doesn't say exactly what it does, it comes close enough and soon enough you'll get used to it. Inherently, most accessibility keywords are pretty meaningless in and of themselves anyway. We just use them enough that we get used to "private" being more restricted than "internal".
The more I think about that answer, the more annoyed I am. private protected doesn't come close to anything at all. It's just completely meaningless, confusing and plain wrong. Imagine explaining C# accessibility modifiers to a group of students. How would you do that? There is absolutely no logic behind that. While I agree that private and internal by themselves are also pretty meaningless and we just got used to them, we already did get used to them so we should not start changing their meaning. private protected is making things worse by saying private means private unless it means internal which is just horribly confusing.
Apr 23 at 1:42 AM
If we take the current C# modifiers and their equivalent in metadata attributes:
   C#                          MetaData Method Attributes

   private                     Private
   protected                   Family
   public                      Public
   internal                    Assembly
   protected internal          FamilyOrAssembly
   ???                         FamilyAndAssembly
While private protected could be confusing, as there is no information about internal, which is currently used to identify assembly level access, what about private protected internal?
  • It would mean that the combination of private and internal modifiers are meaning that the protected qualifier is only visible inside the assembly.
  • It would be like protected internal is implicitly declared with public like public protected internal, meaning that the protected qualifier is visible outside the assembly.
Then the whole table would look like this:
C#                            MetaData Method Attributes
                              
private                       Private
protected                     Family
public                        Public
internal                      Assembly
(public) protected internal   FamilyOrAssembly
private  protected internal   FamilyAndAssembly
This is not ideal, but it doesn't add a new keyword or a contextual keyword.

What do you think?
Apr 23 at 7:57 AM
alexandre_mutel wrote:
What do you think?
I think this is the first reasonable idea. :-)
Apr 23 at 8:47 AM
alexandre_mutel wrote:
  • It would mean that the combination of private and internal modifiers are meaning that the protected qualifier is only visible inside the assembly.
It's still saying it's private when it isn't.
  • It would be like protected internal is implicitly declared with public like public protected internal, meaning that the protected qualifier is visible outside the assembly.
Thus giving another meaning to public.
Apr 23 at 9:08 AM
Edited Apr 23 at 9:09 AM
PauloMorgado wrote:
alexandre_mutel wrote:
  • It would mean that the combination of private and internal modifiers are meaning that the protected qualifier is only visible inside the assembly.
It's still saying it's private when it isn't.
  • It would be like protected internal is implicitly declared with public like public protected internal, meaning that the protected qualifier is visible outside the assembly.
Thus giving another meaning to public.
I agree that this solution is even worse because not only the meaning of private is changed but in addition also the meaning of public (in a certain context, at least).
Apr 23 at 9:12 AM
PauloMorgado wrote:
It's still saying it's private when it isn't.
Thus giving another meaning to public.
Well, in case of private protected internal a member would be private for an external assembly subclassing the type (opposite for public), so I believe the meaning is still relevant. I agree that it is adding a contextual semantic for public and private in case of protected internal, but still valid for each context (protected internal or not)
Apr 23 at 9:21 AM
Edited Apr 23 at 9:22 AM
Accessibility modifiers do not restrict visibility from public, they weaken the default private visibility. See also this post from Eric Lippert: http://blogs.msdn.com/b/ericlippert/archive/2008/04/24/why-can-t-i-access-a-protected-member-from-a-derived-class-part-three.aspx.

Hence, adding private actually means nothing at all. Adding public on the other hand, makes the member public. This model works perfectly with protected internal and would also work with protected or internal as well as protected and internal. But certainly, private protected or public protected internal breaks this way of thinking.

Since this is how C# works (even though it is somewhat counter-intuitive), we should respect that and not completely break the meaning of the visibility modifiers.
Apr 23 at 10:20 AM
In this specific case, we are trying to define a dual visibility, so it is possible to think that adding a private in the context of protected internal would restrict the protected keyword to be only valid inside the assembly. It weakens the declared visibility protected outside the assembly. I agree that it is breaking the meaning of what have been settled in C# so far.
Apr 23 at 11:16 AM
I suggested the idea below in the C# insiders list, and since some people liked it, I'm throwing it in here, just in case. :)

I was thinking about this "private internal" thing back then when Mads said this is coming, and I thought that if the same keywords cannot be used to clearly make a distinction from the current "protected internal" accessibility, then we might reuse another keyword - as C# does in a lot of places. (Think about the different meanings of "this", when using it in different contexts, like in a method body, or in a method's parameter list.)

"assembly" is really close to what "internal" means, so I think "assembly protected" would be good for this purpose. Currently "assembly" is used to annotate certain Attributes. Creating a member like "assembly protected string _s;" would be recognisable as something that is only accessible by descendant types residing in the current assembly.

The downside is that it's a new keyword in describing member access rights. But as I've said, it's already in the language, and used only when creating assembly attributes, so this way it could be reused.
Apr 23 at 11:28 AM
Edited Apr 23 at 11:30 AM
@dfulop: Interesting idea. However, your basically saying yourself that assembly "is really close to what internal means", so by extension protected internal should be pretty close to what assembly protected means. However, your suggesting very different semantics for the latter. For me, the difference between the words assembly and internal doesn't seem to be large enough to justify such a big difference in the semantics of protected internal and assembly protected.

It all boils down to the fact that you have two possible operators to combine the internal and protected visibilities: conjunction and disjunction. Currently, I don't see a good way around that except for clearly stating which operator you want to use, unless you invent completely new keywords for both.

@alexandre_mutel: What exactly do you mean by "dual visibility"? The fact that the behavior differs on whether you're inside or outside of the same assembly? How is that different from protected or private, which depend on whether you're inside or outside of the same class or class hierarchy? The fact that it affects both?
Apr 23 at 12:21 PM
It's not the first time I'm having a discussion about this (and it won't probably be the last).

All purposes seem to be searching for an alternative to private protected. Forget about that.

C# uses two access modifier keywords (protected and internal) for the CLR access modifier FriendOrAssembly. And these two access modifier keywords can be used in any position in the access modifiers list.

Now we want to add the CLR access modifier FriendAndAssembly. The language team came up with private protected. No one likes it but private protected is not the problem that needs solving. The problem that needs solving is coming up with an access modifier specification for the CLR access modifier FriendAndAssembly.

After long consideration, I'm in favor of protectedinternal (not my original proposal) because it conveys the idea that you need to have both to be able to access as protected internal (which already exists and isn't going away for compatibility reasons) conveys the idea that you need either one.

In the end, it's as much of a stretch as any of the other proposals, but that's the one I'm backing.
Apr 24 at 10:02 PM
Unlike everyone else, I actually agree with Mads that 'private protected' is the best choice in the circumstances.

The alternatives are either verbose or plain ugly and do we really want to introduce a new contextual keyword for a feature which won't be used very often?

Anyone who knows what 'internal protected' means will realize that 'private protected' is more restrictive and, as long as you remember that 'private' in this context means private to the assembly rather than to the type, you'll be fine.

Also 'private protected' (or 'protected private') is what C++/CLI uses to represent CIL's 'famandassem' accessibility. So anyone who's familiar with that language will already be familiar with this usage.
Apr 24 at 10:23 PM
Edited Apr 24 at 10:25 PM
@vulpecula: sorry but even though I know C# extensively and have been using it since .net 1.1 (that's 10 years now), I had to look it up and couldn't intuitively figure it out on my own.

At the risk of repeating my second post, 78 people have upvoted this question on stackoverflow:
http://stackoverflow.com/questions/22856215/what-is-the-meaning-of-the-planned-private-protected-c-sharp-access-modifier
Given the nature of the question I think this is quite a lot.

I was familiar with the meaning of internal protected and unlike what you said it didn't help me. I was confused by private in this context, because I am also familiar with the fact that so far private means "visible to the declaring class only".

Maybe C++/CLI experience might help (I have none), but that would be a minority of C# developpers.

I am sorry that I don't have a very bright idea to solve the issue at hand... Currently I am leaning to:
  1. A brand new modifier. E.g. family protected or maybe just family. That will look strange to developpers that don't know about it, but they will look it up rather than get confused.
  2. This is such a corner case that I'm still not convinced that it needs a keyword. I suggested before to use protected and limit the visibility by an attribute well-known by the compiler.
Apr 24 at 11:44 PM
No need to be sorry, jods, as I do understand where you and the others are coming from on this.

The truth is that it's always been an awkward situation.

Even if the C# design team could start again from scratch, I suspect they'd now be having difficulties deciding what to call 'famorassem' access if 'internal protected' were being used instead for 'famandassem'.

In C++/CLI, they use 'public protected' but this isn't very clear either.

Anyway, we're stuck with what we've got and, as there's no ideal solution, it's really just a matter of taste as to what's the least worst solution.
Coordinator
Apr 25 at 5:01 PM
Wow, this is a great discussion!

Given all this feedback, I am certainly going to bring up private protected again with the design team. In the meantime, here are my own thoughts, based on the debate so far. They are my thoughts, not the design team's; I just want to get them out there so you can change my mind before I do bring it up in a design meeting. :-)
  • First of all, I think it is clear that the feature is useful. Disagreement is mainly over syntax, not existence. So let's keep the feature and try to get it right.
  • The syntax should not be confusing. The private protected syntax is confusing because it is composed of existing keywords, without its meaning being a sensible composition of the meaning of those keywords. The existing protected internal has that problem, though to a lesser degree: its meaning is compositional, but it is unintuitive (at least to many folks - me included) that they should be composed with an or, not an and.
  • I'm actually starting to think that needing two keywords is a bit of a failure. I am happy that the only accessibility modifier that needs two keywords today is the one that is mostly useless. I want the new modifier to be a successful first class citizen in the language, and as such it should have a single keyword modifier.
  • The modifier doesn't have to be self-explanatory. The only accessibility modifier that is self-explanatory today is public. All the other ones, private, internal and protected, all have English language meanings that vaguely mean "not public". But which one of them got attached to which exact semantics seems more of a historical accident than a result of deep intrinsic meaning of those words. So I'm actually fine if a new keyword is just yet another word for "not public", that sounds good, looks good and has sort of the right degree of restrictiveness to it. Of course those are subjective and vague criteria. That's nothing new in language design! :-)
So in summary, I'm currently of the mind that we should find a new keyword and use it as a single-keyword modifier with the meaning of "protected and internal". It will take some getting used to, but that's true of any syntax we come up with. At least it won't fire the wrong neurons (like private protected seems to do), and once you do get used to it, it won't have the persistent "ugliness" of a long or multiword modifier poking you in the eye forevermore.

That was a lot of opinion that may already be cause for a great and wonderful amount of disagreement! But even if we do agree on it, of course there's the next battle ahead: which keyword?

I came up with some candidates, and some of my team members supplied more. So here is a "starter list". I've put them in context of a member declaration, to help get the feel of each in context.
exclusive Person[] contents;
limited Person[] contents;
restricted Person[] contents;
confined Person[] contents;
inherent Person[] contents;
enclosed Person[] contents;
I particularly like restricted and inherent, but I think all of them pass muster in my book.

What do you all think? Is this the right line of thinking? What are some other natural candidate keywords?
Apr 25 at 5:24 PM
Edited Apr 25 at 5:24 PM
...won't have the persistent "ugliness" of a long or multiword modifier poking you in the eye forevermore.
Generally, I agree with the sentiment that names should try to be terse (we aren't writing Objective C here after all); however I think there are two strong arguments against the verbosity being an issue:
  • protected and internal and protected or internal access modifiers are both used rarely enough that you wouldn't be writing or reading them very often. And when you do, you know exactly what they mean.
  • Method signatures can already be pretty verbose. I don't think the difference between restricted static async Task Foo() and protected and internal static async Task Foo() is particularly burdensome.
I'm not totally opposed to a new keyword, as I think that's still better than private protected, but I think that solution introduces a weird asymmetry whereby protected internal continues to exist but what is conceptually protected and internal has its own new keyword. I also think adding a new keyword obscures the fact that the modifier is really a conjunction of two existing modifiers. It adds a cognitive burden whereby every developer now has to pause the first time they see that keyword used and look up what exactly it does again. By comparison, protected and internal reuses two keywords people already implicitly understand and makes it crystal clear what the accessibility is.

If you must introduce a new keyword- I'd like to see protected internal get its own new keyword as well. Everyone writing C# 6.0 will be using Roslyn (and thus getting refactoring suggestions anyway), so it would seem pretty simple to offer a contextual suggestion to upgrade old protected internal methods to whatever the new keyword was.

Thanks for participating in these discussions Mads, et al! It's awesome being able to debate features with the language creators.
Apr 25 at 5:39 PM
What about "internal protected"? There's no particularly obvious reason why "protected internal" should be less restrictive than "internal protected" [IMHO, the "AND" restriction is the one that should have been used in the first place, since combining the restrictions on who may use a member increases the member's flexibility to expose types as parameters; I'm not really sure what the "OR" form is useful for], but one can argue that the restriction to the current assembly is more "fundamental" than restriction to derived types [which could be in outside assemblies].
Apr 25 at 6:25 PM
Well, as I said earlier, I preferred 'private protected' to the other suggestions that were on the table up to that point.

I'm not keen on using three keywords and I think that using made-up words would simply be horrible.

I don't really have a problem with using a new (contextual) keyword if everybody thinks this feature warrants it but I do think that the word 'protected' needs to be in there somewhere as 'famandassem' is just a subset of full 'protected' access.

Of the new keywords proposed by Mads, I like 'limited' best as its not too long and conveys the right meaning. My revised preference would therefore now be 'limited protected'.

Another word that could be used would be 'inner' but 'inner protected' sounds too much like 'internal protected' and so might be confusing.
Apr 25 at 7:00 PM
@madst,

Amongst the candidates on your list, I'm kind of a fan of "confined". It has a clear "very limited usage within a well-defined scope" implication. Also, of the candidates, it's the one that I suspect might be least likely to conflict with pre-existing code or be desirable for future features (for example, you might really regret using "restricted" for this in a few years when the keyword would be a perfect fit for something else <g>).

Nicole
Apr 25 at 7:50 PM
Mads,

I disagree that the current words private, protected and internal have only the meaning of non-public. At the least they are logically assigned in our brains to each role.

A random new word does not seem helpful.

These two scopes are inherently conjugations of two existing scopes that everyone understands.

The correct keywords are a little long

protectedIntersectInternal and protectedUnionInternal

The CLR has names for these, but they suffer from the English/bitwise use of And/or and are hard to read.

My newest thought is that we sort of hold our head sideways and say Internal is sort of the part you have to know (default) and make it

intersectprotected
unionprotected

You'll never get them mixed up, they are long, but not in a frightening way. Because they differ at the start, they can be read (unlike and and or in the middle of the word).

I'd rather see the P's capped, but I know we're stuck on the antique notion that people actually type keywords.

They won't give a misleading impression, are a tad odd so you have to look it up once, and once you get it, they can’t be confused (due to the common use and the bitwise use)

Agreed that this is a good feature. It's been in .NET since the beginning I think, and it's just silly that we can't raise it in C#.
Apr 25 at 8:11 PM
supercat wrote:
What about "internal protected"? There's no particularly obvious reason why "protected internal" should be less restrictive than "internal protected" [IMHO, the "AND" restriction is the one that should have been used in the first place, since combining the restrictions on who may use a member increases the member's flexibility to expose types as parameters; I'm not really sure what the "OR" form is useful for], but one can argue that the restriction to the current assembly is more "fundamental" than restriction to derived types [which could be in outside assemblies].
internal protected and internal protected mean the same thing C#.
Apr 25 at 8:22 PM
madst wrote:
Wow, this is a great discussion!

Given all this feedback, I am certainly going to bring up private protected again with the design team. In the meantime, here are my own thoughts, based on the debate so far. They are my thoughts, not the design team's; I just want to get them out there so you can change my mind before I do bring it up in a design meeting. :-)
  • First of all, I think it is clear that the feature is useful. Disagreement is mainly over syntax, not existence. So let's keep the feature and try to get it right.
  • The syntax should not be confusing. The private protected syntax is confusing because it is composed of existing keywords, without its meaning being a sensible composition of the meaning of those keywords. The existing protected internal has that problem, though to a lesser degree: its meaning is compositional, but it is unintuitive (at least to many folks - me included) that they should be composed with an or, not an and.
  • I'm actually starting to think that needing two keywords is a bit of a failure. I am happy that the only accessibility modifier that needs two keywords today is the one that is mostly useless. I want the new modifier to be a successful first class citizen in the language, and as such it should have a single keyword modifier.
  • The modifier doesn't have to be self-explanatory. The only accessibility modifier that is self-explanatory today is public. All the other ones, private, internal and protected, all have English language meanings that vaguely mean "not public". But which one of them got attached to which exact semantics seems more of a historical accident than a result of deep intrinsic meaning of those words. So I'm actually fine if a new keyword is just yet another word for "not public", that sounds good, looks good and has sort of the right degree of restrictiveness to it. Of course those are subjective and vague criteria. That's nothing new in language design! :-)
So in summary, I'm currently of the mind that we should find a new keyword and use it as a single-keyword modifier with the meaning of "protected and internal". It will take some getting used to, but that's true of any syntax we come up with. At least it won't fire the wrong neurons (like private protected seems to do), and once you do get used to it, it won't have the persistent "ugliness" of a long or multiword modifier poking you in the eye forevermore.

That was a lot of opinion that may already be cause for a great and wonderful amount of disagreement! But even if we do agree on it, of course there's the next battle ahead: which keyword?

I came up with some candidates, and some of my team members supplied more. So here is a "starter list". I've put them in context of a member declaration, to help get the feel of each in context.
exclusive Person[] contents;
limited Person[] contents;
restricted Person[] contents;
confined Person[] contents;
inherent Person[] contents;
enclosed Person[] contents;
I particularly like restricted and inherent, but I think all of them pass muster in my book.

What do you all think? Is this the right line of thinking? What are some other natural candidate keywords?
I still like protectedinternal better than any of those. protected internal (and internal protected) conveys me a meaning of or -> protected or internal while joining the two words a conveys me a meaning of _and -> protected and internal.
  • There already exists a two word keyword: foreach
  • People already know (or should know) what protected and internal mean and it would be easier to explain that protected internal and protectedinternal are different ways of combining the same access modifiers.
The bad part is that inadvertently hitting space, delete or backspace can change one into the other.

@Mads, I can understand the reasoning behind private protected. Can you elaborate why each of the options was chosen as an option to consider?
Apr 25 at 11:56 PM
restricted is the first suggestion that I actually like.

I agree with Mads' opinion that the name doesn't have to be self explanatory, anymore than private or protected. are. You can't guess what protected means, you have to learn; and it will be the same with the new keyword, whatever it is.

restricted is short, clearly evokes an accessibility level, isn't weird like private protected or proternal, and isn't as confusing as most of the other suggestions.
Apr 26 at 6:32 AM
Thanks Mads for the feedback.

Seems the current design of protected internal is making our life difficult to find a compromise on this. So if we are up to the point to add a new keyword, well, I will probably reserve my vote for restricted unless there is something better coming up.
Apr 26 at 8:22 AM
When this came up on insiders, I suggested:
protected for internal
For the following reasons:
  • It does not require adding new keywords (like 'and' and 'or')
  • It makes sense within (and further solidifies) the C# idiom that members start out private and you grant access - in this case you grant "protected" but it's limited to "internal" - thus building on existing C# knowledge
  • Not ambiguous (like "protected and internal" meaning different things in Boolean vs English)
  • Clearly an access modifier
But I do think that "private protected" isn't bad. The fact that it doesn't make sense is a positive, because it means that you must look up/learn/remember what it means. It's far better than some of the other options where people could guess what they mean incorrectly.
Apr 26 at 2:35 PM
My instinct on this is one of the following:
  1. When you look at the protected internal modifier, it's the protected modifier which is resulting in exposing the member to other assemblies. Based on this, it seems the protected keyword is the part of protected internal which needs to be altered in order to be FamilyAndAssembly. The natural way to do this with existing keywords would be to use private internal to mean FamilyAndAssembly, and protected internal to mean FamilyOrAssembly.
  2. The C# language allows for partial classes, but restricts the context-sensitive keyword partial to immediately preceding the word class. In a similar manner, we could introduce a context-sensitive keyword immediately preceding protected, such as assembly protected. Another option is a context-sensitive keyword immediately preceding internal; a natural solution here seems to be restricted internal. The latter could arguably be shortened to just restricted without making things more confusing than they otherwise would be.
Apr 26 at 5:09 PM
Edited Apr 26 at 5:12 PM
I like the sharwell's reasoning in first paragraph. Nothing in private internal suggests it will be visible outside the assembly. And by comparing the two you see that private internal is more restrictive than protected internal which holds.

Given the difference in opinions, the question is whether we need it though. You can get FamilyAndAssembly access with internal abstract members, which is already used in .NET Framework.
Apr 26 at 5:34 PM
Edited Apr 26 at 5:34 PM
JanKucera wrote:
Given the difference in opinions, the question is whether we need it though.
The feature is useful; it would be a pity to drop it just because we can't agree on a keyword...
You can get FamilyAndAssembly access with internal abstract members, which is already used in .NET Framework.
abstract isn't an access modifier, so an internal abstract method has internal access, which is Assembly, not FamilyAndAssembly. Any class in the same assembly can access the method, not just derived classes.
Apr 26 at 11:14 PM
sharwell wrote:
The natural way to do this with existing keywords would be to use private internal to mean FamilyAndAssembly, and protected internal to mean FamilyOrAssembly.
Why would that be natural? protected means that it's accessible by derived types. In CLR terms, that's Friend. Although private internal relates to the CLR Assembly, it says nothing about the Friend part. private internal would be the same as just private because it's always assembly bound.
Coordinator
Apr 27 at 7:19 AM
Note: In the VB language design meeting on this topic (VM LDM 2014-03-12), we chose to add two new keywords "ProtectedAndFriend" and "ProtectedOrFriend", as exact transliterations of the CLI keywords. This is easier in VB than in C# because of VB's tradition of compound keywords and capitalizations, e.g. MustInherit, MustOverride.
Apr 27 at 8:59 PM
I've just thought of another potential keyword to be added to the list: sheltered.

If we're just going to use one keyword (instead of two or three), I like this word because it conveys the meaning of being both protected and internal to something else at the same time.
Apr 27 at 11:12 PM
Edited Apr 27 at 11:14 PM
In the spirit of the intersection of one of only two hard problems in computer science (naming things, cache invalidation and off-by-one errors) and good-old bike-shedding, I propose overprotected (maybe jokingly).

I agree with Mads that a new word is an interesting direction. sheltered sounds great, but at least to me, it also brings weird connotations of neglect. safe might work, but its antonym unsafe is already in play with other connotations (unless you'd want a safe unsafe static dynamic method...). Whatever the word, it should be relatively neutral, as far as that's even possible, and fit mentally as "tighter than protected, looser than private".

With that in mind, how's shielded?
Apr 28 at 10:01 PM
I'm a visual person. Consider the following diagram (does not enumerate private and public - just protected/internal combos):
+-------------------------------+
| Assembly1                     |
|+-----------------------+      |
|| <modifier> void Foo ()|      |
|+-----------------------+      |
|    ^                          |
|    |                          |
|+--------+          +--------+ |
|| Foo(); | A      B | Foo(); | |
|+--------+          +--------+ |
+----^--------------------------+
     |
+----|--------------------------+
|    |                Assembly2 |
|+--------+                     |
|| Foo(); | C                   |
|+--------+                     |
+-------------------------------+
Combos for access are:

A only - modifier is FamilyAndAssembly (the name we're debating)
B only - N/A
C only - N/A
AB only - internal
AC only - protected
BC only - N/A
ABC only - protected internal (FamilyOrAssembly)

So FamilyAndAssembly is pretty restrictive as folks have pointed out. The problem with using multiple keywords for FamilyAndAssembly is that C# has set a precedent where modifier keyword order shouldn't matter and each individual keyword should make sense in isolation. "protected" by itself is meaningful as is "internal" and combined together you can intuit that you get the union of the two. "private" and "protected" make sense individually but based on their individual meanings, combining them doesn't result in something you can easily intuit (in fact it appears to be an oxymoron). OTOH the primary restriction is "protected" which is restricted a bit more by only applying to derived types contained in the same assembly. So it is desirable to have "protected" in the name.

I find myself leaning towards assemblyprotected - maybe even overprotected. Although I can hear the jokes now about over protective base classes being a problem similar to sealed classes. :-) However if it came down to a choice between "private protected" and "restricted", I'd vote for "restricted".
Apr 28 at 10:11 PM
r_keith_hill wrote:
So FamilyAndAssembly is pretty restrictive as folks have pointed out. The problem with using multiple keywords for FamilyAndAssembly is that C# has set a precedent where modifier keyword order shouldn't matter and each individual keyword should make sense in isolation. "protected" by itself is meaningful as is "internal" and combined together you can intuit that you get the union of the two. "private" and "protected" make sense individually but based on their individual meanings, combining them doesn't result in something you can easily intuit (in fact it appears to be an oxymoron). OTOH the primary restriction is "protected" which is restricted a bit more by only applying to derived types contained in the same assembly. So it is desirable to have "protected" in the name.

I find myself leaning towards assemblyprotected - maybe even overprotected. Although I can hear the jokes now about over protective base classes being a problem similar to sealed classes. :-) However if it came down to a choice between "private protected" and "restricted", I'd vote for "restricted".
Why would assemblyprotected be better than protectedinternal?

There's nothing more restricted than private. Wouldn't a restrictedish modifier named restricted be confusing?
Apr 28 at 10:17 PM
I think VB has it right here. If multi-word identifiers are problematic, protectedandinternal and protectedorinternal also seem fine. The lack of camel casing is not ideal, of course, but I think it's still clearer than private protected or a new keyword.
Apr 28 at 11:12 PM
Edited Apr 28 at 11:15 PM
PauloMorgado wrote:
Why would assemblyprotected be better than protectedinternal?

There's nothing more restricted than private. Wouldn't a restrictedish modifier named restricted be confusing?
I was thinking assemblyprotected just to clearly distinguish it from protected internal / internal protected.

The problem with protectedinternal is how visually close in appearance it is to protected internal. While skimming code your mind just might fill in the missing space. Another problem is it isn't clear if the implied conjunction is and or or? Besides, if we're going to go with multi-word keywords then let's just use protectedandinternal and clear up any confusion. :-)

BTW I'm not a fan of restricted - only that I like it a bit better than private protected. Neither is ideal.

FWIW I can appreciate why the C# team struggled with the name of this feature. I've yet to see that "head-slapper" obvious name.
Apr 28 at 11:36 PM
I agree with you about protectedinternal, but I'm not too found of shoehorning other words just not to use it.

I think one thing we all can agree. no one likes private protected!
Apr 29 at 1:03 AM
Edited Apr 29 at 1:09 AM
It's worth pointing out that protectedinternal (no space) is going to result in some less-than-ideal behaviour from the auto-complete in Visual Studio.

(Amongst the many other problems with reading and writing it, as have already been pointed out.)

Actually... come to think of it, this is a problem with all of the other no-space word-reusing options.
Apr 29 at 7:19 AM
I'm really more concerned that adding or removing a space would change the semantics of the program. Although it would be an obvious longer than the others modifier. At leas for now.

It's just that, for me, with all the caveats, it's the only option that builds upon existing C# concepts and practices.
Apr 29 at 2:06 PM
MgSam wrote:
I think VB has it right here. If multi-word identifiers are problematic, protectedandinternal and protectedorinternal also seem fine. The lack of camel casing is not ideal, of course, but I think it's still clearer than private protected or a new keyword.
I totally agree with this.
Otherwise, I like overprotected, since it's the only proposal that still refers to protected.
Apr 29 at 7:30 PM
Surely semiprotected would be better than overprotected as it's protected inside the assembly but not outside it. Also it doesn't have the latter's rather jokey connotations.

However, personally, I'm not keen on any of these long or portmanteau words which I think are at odds with the aesthetics of the language.

Although I've come around to Mads' revised view that it would be better to have a single keyword for the new modifier, I'd prefer a shorter word such as sheltered, shielded or guarded which are synonyms of protected.

One point that's worth making is that within an internal class (the default), the protected modifier already means protected AND internal because it's constrained by the access of the class itself. This means that, most of the time, the new modifier (whatever it turns out to be) could be used interchangably with protected. It would therefore make sense for it to have a similar meaning and length.
Apr 29 at 10:01 PM
This is a tough one. I'd have to vote for protectedandinternal as well. It's ugly, but it is least likely to require repeated trips to the help documentation. And, given some of the hostile initial reactions to the concept being represented, maybe ugly is appropriate (though I personally have wanted this feature since .NET 1.1).

Interestingly, my initial reaction was positive toward shielded, but then later I realized I was already starting to question my memory of exactly what it meant ("I think it's protected and ... um ... something"). So, I'm back to ugly but unambiguous. Says what it means, and means what it says.
Apr 29 at 10:44 PM
Edited Apr 29 at 10:44 PM
I still say burn it to the ground.

Since that doesn't seem likely, give it an ugly name like protectedandinternal so people understand where they start from.

It just boggles my mind that any of you would ever want to be subjected to this. It breaks the entire promise of inheritance, that you can access all of your base's nonprivate members! So now if a school ever teaches C# they'll have to explain that inheritance can be entirely different in C#.
Apr 30 at 3:20 AM
dotnetchris wrote:
I still say burn it to the ground.

Since that doesn't seem likely, give it an ugly name like protectedandinternal so people understand where they start from.

It just boggles my mind that any of you would ever want to be subjected to this. It breaks the entire promise of inheritance, that you can access all of your base's nonprivate members! So now if a school ever teaches C# they'll have to explain that inheritance can be entirely different in C#.
That's already the case with C# with the internal accessibility modifier, or with Java and members decorated with no modifier.
Apr 30 at 4:54 AM
Edited Apr 30 at 4:55 AM
May I offer the following as candidate keyword for 'private protected'?
  • caged
  • enclosed
  • snared
  • confined
  • incarcerated
  • imprisoned
  • cloaked
  • masked
  • detained
  • jailed
I also like guarded :)
Apr 30 at 8:44 AM
Edited Apr 30 at 8:46 AM
I have been reading this post carefully and I have come to the conclusion that, as dotnetchris states, that the new accessibility being proposed would give a new meaning to inheritance in C#.

Having said that, I have not found, yet, a strong reason to consider it an abomination, though, from the viewpoint to OOP. But, as many, I do not like the combo "private protected", since it could be considered by some devs as counter-intuitive.

1) Using And/Or: many of you have been suggesting to use "protected and internal" and "protected or internal", instead of "private protected" and "protected internal". At first, it looks great, but when you look on "protected and internal" it could end up being more counter-intuitive than "prvate protected". Some devs may ask: "why is the word "internal" there if it is not internal?". And if you look on "protected or internal", even though it is not a XOR, a few may also ask: "why one or the other when I want both?". This rationale would apply to new keywords like "protectedandinternal" and "protectedorinternal".

So, I would let alone "protected internal" and try to resolve only the issue with "private protected", which leads me to point 2) below.

2) Introducing new keywords: many words have been suggested like "protectedandinternal", "assemblyprotected", "restricted", "overprotected", "confined", and so on so forth. I have thought of alternatives like "inner protected", "innerprotected", "self", "self protected" or "selfprotected", but my concern here is that we would have to learn and remember a new keyword whose semantic could turn out NOT to be that intuitive for many of us.

Which takes me to point 3).

3) Using an existing keyword: why not using just one existing keyword instead of using two keywords and or trying to come up with new ones? In this case we would not have to learn and remember new combos or keywords, and instead, we would be adding a new semantic to an existing word for member's accessibility. This rationale is the one that most appeals to me, but which existing keyword would I choose?

Searching the list of keywords, the one I like the most is "sealed", which so far only applies to classes. And therefore, we would be giving it a new meaning for members: "a member (field or operation) that can only be accessed by its declaring class and or its specifications on the same assembly where the declaring class is defined".

Thus, when you mark a field or operation (including properties) with "sealed", you will be telling the compiler what it is meant with "private protected" but on a cleaner way, which in my opinion is much more intuitive (note: the compiler will have to treat "sealed internal" or "internal sealed" as an error, since in practice it offers the same accessibility as internal).

Hope you guys agree on this ...
Apr 30 at 8:49 AM
Ultrahead wrote:
Searching the list of keywords, the one I like the most is "sealed", which so far only applies to classes.
Sorry, it doesn't. Sealed already can be applied to methods, to stop a virtual method from being overridable. That would give two meanings to the same keyword at the same place.
Apr 30 at 9:03 AM
Edited Apr 30 at 9:37 AM
Well, in that case -being loyal to my rationale above- my other options for using only one word were: "base", "lock" and "yield".

If it has to be two words then I'd go with "base protected", "this protected" or "lock protected". And if a new keyword is introduced to build a combo, i'd prefer "assembly protected", "inner protected" or "self protected".

I still do not like the idea of introducing a new keyword, one keyword, like "protectedandinternal", "confined", etc.
Apr 30 at 9:34 AM
Edited Apr 30 at 9:39 AM
Ultrahead wrote:
Well, in that case, my other options were "base", "lock" and "yield", and if it has to be two words then I'd go with "base protected" or "lock protected".
In my opinion, lock and yield have meanings that are too different from a simple accessibility modifier to be used: lock might imply that a method is single-threaded (similar to MethodImplAttributes.Synchronized) while yield is too closely related to iterators.

base might work, but remember that modifiers can be placed in any order. While base protected void Foo() conveys the right meaning because there aren't many ways to interpret it, consider protected async virtual base sealed void Foo() instead. Personally, I can't tell that base is a modifier to protected, even with knowing it. I think the keyword must have a meaning on its own.
Apr 30 at 10:13 AM
Edited Apr 30 at 10:51 AM
MrJul wrote:
I think the keyword must have a meaning on its own.
Agreed, but as usual, it is also a matter of getting used to it.

Take the keyword "protected" for instance, per se, would you know beforehand that it has to do with inheritance? Frankly, my answer here would be: "no". Once you start working with the language, you get used to its meaning. Ditto with "confined", "shelter" and other words being proposed.

So, I agree in the case of "lock" but I still believe "base" is not a bad choice (base async virtual void Foo())".

Other suggestions:

this async virtual void Foo()
yield async virtual void Foo() (even if it is strongly related to iterators)
self async virtual void Foo() (if it has to be a new word)
scoped async virtual void Foo() (ditto)
protectedin async virtual void Foo() (ditto)
local async virtual void Foo() (ditto)
procal async virtual void Foo() (entering the space of weirdness)

EDIT: i guess you meant protected async override base sealed void Foo() instead of virtual.
Apr 30 at 3:16 PM
Heheh, the crazy number of keywords that can be placed on one member declaration really cries out for a "single" keyword solution for FamilyAndAssembly. Since the primary accessibily is protected (just a more restricted version) it sure seems like protected ought to be in the name. I kind of laughed at it at first but I'm really warming up to overprotected.
Apr 30 at 4:30 PM
r_keith_hill wrote:
Heheh, the crazy number of keywords that can be placed on one member declaration really cries out for a "single" keyword solution for FamilyAndAssembly. Since the primary accessibily is protected (just a more restricted version) it sure seems like protected ought to be in the name. I kind of laughed at it at first but I'm really warming up to overprotected.
Why not just FamilyAndAssembly? atleast it would be uniform.

Or assembly protected as a 2 word. atleast assembly protected and FamilyAndAssembly correctly imply what it means.
Apr 30 at 4:36 PM
Edited Apr 30 at 7:24 PM
Halo_Four wrote:
That's already the case with C# with the internal accessibility modifier, or with Java and members decorated with no modifier.
Internal at the member level is basically equivalent to private member and a helper class that is marked internal at the class level. I don't see this violating inheritance. I would also argue that internal at the member level would likely be better suited to be done as such with a private member. With a separate helper class and if necessary make the helper class itself internal.

If you're serious about exposing stateful members and not just pure methods as internal, that is not a project i want to be involved with. I can't imagine the pain that will lead to that you have different classes in an assembly messing with state of an unowned friend class. [edit: add pure qualifier]
Apr 30 at 5:23 PM
dotnetchris wrote:
r_keith_hill wrote:
Heheh, the crazy number of keywords that can be placed on one member declaration really cries out for a "single" keyword solution for FamilyAndAssembly. Since the primary accessibily is protected (just a more restricted version) it sure seems like protected ought to be in the name. I kind of laughed at it at first but I'm really warming up to overprotected.
Why not just FamilyAndAssembly? atleast it would be uniform.

Or assembly protected as a 2 word. atleast assembly protected and FamilyAndAssembly correctly imply what it means.
The issue with using FamilyAndAssembly is that C# keywords are all lower case and at the moment I can't think of any that are multiword. The C# style equivalent of FamilyAndAssembly would be protectedandinternal. It does have one small problem that Kathleen has pointed out. It depends on how your interpret "and". If folks interpret that to mean that accessibility is conferred to derived types and internal types they would be wrong. It isn't a stretch to see how folks might interpret it that way. It is really more of an intersect (derived types intersected with internal types). This is the problem with using two keywords in general - besides ordering and the fact that a bunch of other keywords can get put in between. In the case of multiple keywords on a member decl, each keyword embues some additional behavior. In the case of protected internal, protected says that all derived types have access and then internal comes along and says that all types inside that assembly also have access. Order doesn't matter. The case of FamilyAndAssembly is decidedly different. protected would declare all derived types have access and then some other keyword (assembly, private, etc) would then take away (restrict) the accessibility proffered by protected? I guess that could work if the additional keyword is only valid when placed before protected e.g. assembly protected works but protected assembly, assembly async protected, etc don't because assembly is a modifier of the protected accessibility modifier. But that might seem odd to folks as they've been happily putting all these member decl keywords in whatever random order they desire. :-)
Apr 30 at 5:50 PM
@r_keith_hill My own experience (which correlates with what I've seen people mention online) is that people think about accessibility levels as restricting. That is, each modifier further restricts the visibility of whatever its placed on (even if according to spec, the reverse is actually true). Therefore, the natural conclusion for protectedandinternal is that it applies protected and internal restrictions (the intersect, just as if you had written an if statement with an && clause), and this is in fact what it would do.

This is also why the existing protected internal modifier is so flawed; most people don't think of accessibility modifiers as widening. I mentioned to the developers I work with what that the proposed private protected was the equivalent of protected and internal and the reaction I got was, "doesn't protected internal do that already?"

This is why I think you can kill two birds with one stone by deprecating protected internal and adding protectedandinternal and protectedorinternal. C# is a pit of quality language, and this feature currently deceives people by being unclear. I think being as explicit as possible and reusing the existing operator names is the best way to keep people in that pit of quality.
Apr 30 at 6:18 PM
dotnetchris wrote:
It just boggles my mind that any of you would ever want to be subjected to this. It breaks the entire promise of inheritance, that you can access all of your base's nonprivate members! So now if a school ever teaches C# they'll have to explain that inheritance can be entirely different in C#.
If you are writing code within the same assembly, you can access your base-class members. If you are writing code in another assembly, then from your perspective the base-class members will behave exactly as if they were "private". Code outside an assembly neither knows nor cares about the which members would be visible to other code in that assembly. If one assumes that code within an assembly is going to refrain from messing with things it shouldn't, the biggest effect of the new modifier will probably be to allow for methods which have a parameter of an internal type and a parameter of a protected type (such a method could not exist without access being restricted to derived types within the same assembly).
Apr 30 at 6:24 PM
Edited Apr 30 at 6:29 PM
MgSam wrote:
This is also why the existing protected internal modifier is so flawed; most people don't think of accessibility modifiers as widening. I mentioned to the developers I work with what that the proposed private protected was the equivalent of protected and internal and the reaction I got was, "doesn't protected internal do that already?"
This is why I think you can kill two birds with one stone by deprecating protected internal and adding protectedandinternal and protectedorinternal. C# is a pit of quality language, and this feature currently deceives people by being unclear. I think being as explicit as possible and reusing the existing operator names is the best way to keep people in that pit of quality.
Interesting proposal for deprecation. I think at least a compiler warning or Code Analysis rule would be warranted, since protected internal definitely fails the pit of quality test. FWIW, I've had exactly the same experience with one of my coworkers in the past. In fact, the coworker was actually adding internal to methods which were already just protected in an effort to further restrict visibility - oops.

I'm still leaning towards the long ugly keywords. Like @r_keith_hill, I'm also starting to half-seriously understand the appeal of underprotected and overprotected, though I can't imagine putting those sorts of value judgments into a language's keywords. It would probably have to be something more like lessprotected and moreprotected, but all of those still fail my "can I remember what this means without re-reading the language spec" test. The vague words are really no better than something like protected++ or protected--.
Apr 30 at 6:58 PM
This is why I think you can kill two birds with one stone by deprecating protected internal
Deprecating 'protected internal' might have an additional advantage. This is only case where multiple accessibility modifiers are involved. If you say that only one accessibility modifier is allowed then you get around the modifier ordering problem mentioned by nmgafter and you can use & and | like Halo_Four proposed.

In grammar terms:

method-modifier: new static virtual sealed override abstract extern async accessibility modifier
accessibility modifier: public private protected internal (protected & internal) (protected | internal)

I think it's far better than inventing new keywords.
Apr 30 at 7:10 PM
MgSam wrote:
@r_keith_hill My own experience (which correlates with what I've seen people mention online) is that people think about accessibility levels as restricting. That is, each modifier further restricts the visibility of whatever its placed on (even if according to spec, the reverse is actually true).
Are there any cases where adding a modifier expands upon pre-existing accessibility rather than replacing it? I would consider it more natural to regard the behavior of modifiers as being more like that of constructors, where a default is assumed if nothing is specified, but specifying anything cancels the default.

Also, private as implemented in C# is not the most restrictive modifier possible. It would also be possible to have "instance private" and "instance protected" access levels, which could not be accessed upon any instance other than this or base. If Widget declares a private field Woozle, and any instance uses the Woozle of any instance other than itself, such usage will mean that outside code which needs a Widget will need something with a private field Woozle, when outside code really shouldn't care about such things; refactoring to remove that requirement may be difficult. If Size were instance-private, and if Widget exposed a factory method rather than a constructor, then it would be possible to replace Widget with an abstract class with abstract public members; its factory method would construct an instance of ConcreteWidget (containing the code from Widget) or other class, as appropriate. If the factory parameters indicated no Woozle was needed, the factory could create an object without one.
Apr 30 at 7:13 PM
I'm really surprised that overprotected seems to be winning some favor. To be clear: it was a joke, although I also consider the composite form internal protected a different kind of joke...

After reading all the posts and continuing to stew, what I'm valuing personally is something that says "more protected than even protected". overprotected, for all else it does, certainly does that. Mads and btjagilent have made complementary points: it's a bit arbitrary at first, but it's very useful if the words are either mnemonics or at least lend themselves to easy ordering amongst themselves. This is at least largely a mug's game.

protectedinside? protectedlocal? protectedrestricted / protectedaccessible? protectedtoinner / protectedtoouter? concealed? intramural?
Apr 30 at 7:52 PM
Edited Apr 30 at 7:53 PM
JesperTreetop wrote:
I'm really surprised that overprotected seems to be winning some favor. To be clear: it was a joke, although I also consider the composite form internal protected a different kind of joke...
After reading all the posts and continuing to stew, what I'm valuing personally is something that says "more protected than even protected".
Yes, I was interpreting overprotected as a joke, didn't mean to imply I was seriously supporting it. But, as you say, the concept behind the joke has merit since it demonstrates our goal.
protectedinside? protectedlocal? protectedrestricted / protectedaccessible? protectedtoinner / protectedtoouter? concealed? intramural?
protectedtointernal?
protectedtoassembly?

No need to introduce brand new terminology for existing concepts, IMHO, but I like your idea of introducing "to" as a less-ambiguous alternative to "and".
Coordinator
Apr 30 at 8:07 PM
Edited Apr 30 at 8:15 PM
The C# team has made a poll. Please vote with your preferences here:

https://www.surveymonkey.com/s/8YHQPGF



PS. Jasper and btjagilent, sorry, I created the survey prior to your suggestions.
Marked as answer by lwischik on 4/30/2014 at 1:07 PM
Apr 30 at 8:28 PM
Some of these suggestions are hilarious but I think it detracts from the discussion to have the absurd choices (jailed? somewhat private? imprisoned?) mixed in with more serious ones. I hope you guys make an additional poll after this one with finalists.

Also, I think you should also take any poll done on SurveyMonkey with a big grain of salt as they only keep track of who has voted already by using a browser cookie.
Apr 30 at 8:41 PM
I'm loving protecteder. So sad there isn't more protectedest :(
Apr 30 at 8:43 PM
I've taken the poll. Let's see how this shakes out and whether there's at least a clear way forward or a few clusters of different opinions in which case people will be pissed no matter which decision is made.
Apr 30 at 9:09 PM
r_keith_hill wrote:
The issue with using FamilyAndAssembly is that C# keywords are all lower case
Indeed!
and at the moment I can't think of any that are multiword.
foreach --> For Each.
Apr 30 at 9:46 PM
PauloMorgado wrote:
and at the moment I can't think of any that are multiword.
foreach --> For Each.
There are a few, actually...

namespace
readonly
sizeof
typeof
stackalloc
orderby
Apr 30 at 10:22 PM
Poll taken.

Maybe both protected and protected internal could be substituted with:

protectedoutward = the current "protected"
protectedinward = the proposed "private protected"
protectedinternal = the current "protected internal".
May 1 at 7:10 AM
My 2 cents.
Voted for single new keyword restricted, here's why:
I don't think we should change the naming of existing keywords or even make protected internal
obsolete or introduce new composed keywords with AND or OR.
And since most devs probably know, that protected internal means protected or internal, Having any other combination with two or even three words might be misleading.
New single keyword seems to me like a best choice.
May 1 at 9:59 AM
I agree entirely with what Necroman has just said except that I've voted for sheltered as first preference with restricted as a 'tactical' second preference.
May 1 at 1:39 PM
I voted for restricted as my first choice but still does not convince me since its meaning is not intuitive for family inside the assembly.

I'd prefer another word like 'native', instead.
May 1 at 6:07 PM
If you think of it, "native" is another way to say "familiar", but being picky, it would also mean "close to the root" (even more than "familiar"), which in this case would mean "a familiar within the scope of the assembly".
May 1 at 6:48 PM
Ultrahead wrote:
I'd prefer another word like 'native', instead.
Given that we are writing manage (thus not native) code that in the near future can be compiled to native, that keyword in that context would be very misleading.
May 1 at 6:51 PM
Well, then use "familiar", instead. But I still like more "native".
May 1 at 7:03 PM
Just call it superinternal. It is like internal, but bit more restrictive.

Note that the modifiers work like this:

When you don't add anything, it is private, the most restricted.

With every keyword you add, you open the member more. That is why protected internal means opened to family (opened by keyword protected) and to assembly (opened by keyword internal).

This logic works well. The new private protected modifier would break this logic. If I saw private protected, I would think that it is the same as protected.

Since there is no mechanism for closing the member access, each keyword is just for opening, we have two options to stay logical:
  • Introduce new keyword for the access (superinternal as I suggested makes the most sense for me)
  • Introduce mechanism for closing access too (now we can just open it)
I vote for the first option of these two, since the second one seems uselessly complicated.
May 1 at 7:54 PM
tompazourek wrote:
Just call it superinternal. It is like internal, but bit more restrictive.
The same argument could be made for superprotected
Note that the modifiers work like this:

When you don't add anything, it is private, the most restricted.
For non-inner types it's internal.
With every keyword you add, you open the member more. That is why protected internal means opened to family (opened by keyword protected) and to assembly (opened by keyword internal).

This logic works well. The new private protected modifier would break this logic. If I saw private protected, I would think that it is the same as protected.
Totally agreed.
Since there is no mechanism for closing the member access, each keyword is just for opening, we have two options to stay logical:
  • Introduce new keyword for the access (superinternal as I suggested makes the most sense for me)
  • Introduce mechanism for closing access too (now we can just open it)
I vote for the first option of these two, since the second one seems uselessly complicated.
I just don't like superinternal because it says nothing about protected.
May 1 at 9:11 PM
I will just say I would not mind breaking it to fix this.

It is too complicated to swiftly add something at this point...
May 2 at 6:00 PM
Edited May 2 at 6:18 PM
Me neither, and for those that don't like the word native, given the fact that .NET Native has arrived, my new proposal:
  • familiar = the current "protected"
  • intrinsic = the proposed "private protected"
  • familiarinternal = the current "protected internal".
EDIT: sorry, "internalized" was my second option for "private protected" (instead of "intrinsic").
May 2 at 7:56 PM
I'll throw my hat in here.

Given that there will be a finite amount of modifiers (6), one should know exactly the circumstances in which to use them. I would consider it completely reasonable to memorize them and their behavior, including the original "private protected." Though it's true that currently you are able to alter the order of the signature without it changing anything, perhaps we can have a "hybrid" modifier separated by spaces: that's right, keep it the same "private protected" but error/warn/disallow them to be separated. They must always stay together. This way an unfamiliar developer gets a hint as to "compiler says these should stay together for some reason, I should probably know why."

A downside is that Eric Lippert's comment on adding-makes-less-restrictive becomes false.
May 2 at 9:41 PM
This is the perfect chance to also fix "protected internal" and sync both features correctly.
I have thought of a new keyword for the proposed feature: "packaged". Too bad it is not in the poll...

There must be a way to make both features obvious, reasonable, and clean!!!
May 3 at 2:26 PM
Alekdias wrote:
I have thought of a new keyword for the proposed feature: "packaged". Too bad it is not in the poll...
If a new keyword is needed, packaged does sound quite nice.
May 5 at 4:02 PM
lwischik wrote:
The C# team has made a poll. Please vote with your preferences here:

https://www.surveymonkey.com/s/8YHQPGF



PS. Jasper and btjagilent, sorry, I created the survey prior to your suggestions.
Can we see the results of this survey?
Coordinator
May 6 at 4:49 AM
dotnetchris wrote:
Can we see the results of this survey?
I'll definitely post the raw poll results and summary! Want to hold off for a bit first, though, so that seeing the results doesn't influence peoples' votes...
May 8 at 7:07 AM
In the poll I gave the second place to "private protected" because of how lengthy it is and so i vote for the single keyword variant "sheltered". But I regret it. I will use this feature not nearly often enough to be bothered by it's lengthiness. So you can add one to "private protected" and subtract one from "sheltered". "private protected" is not an abomination, it's a reasonable compromise. There is nothing difficult in learning that there are only six accessibility kinds in C# and they called so and so. This feature is not nearly important enough to introduce new keywords or unusual syntax for it when there is a ready-made acceptable solution. I think C# should be about practice and way less about philosophy.
May 8 at 11:56 AM
Quinisext wrote:
In the poll I gave the second place to "private protected" because of how lengthy it is and so i vote for the single keyword variant "sheltered". But I regret it. I will use this feature not nearly often enough to be bothered by it's lengthiness. So you can add one to "private protected" and subtract one from "sheltered". "private protected" is not an abomination, it's a reasonable compromise. There is nothing difficult in learning that there are only six accessibility kinds in C# and they called so and so. This feature is not nearly important enough to introduce new keywords or unusual syntax for it when there is a ready-made acceptable solution. I think C# should be about practice and way less about philosophy.
I agree. I think the best token will be whocares.

The interesting things are happening here: https://roslyn.codeplex.com/discussions/541334 (just a little bit of self promotion)
Coordinator
May 13 at 1:42 AM
Edited May 13 at 1:43 AM
Thank you everyone for your poll entries! The raw data is here: PrivateProtectedSurveyResults.zip

528 people voted

HOW MANY PEOPLE LIKE THE LEADING CANDIDATES:

assembly protected - 39%
restricted - 19%
protected & internal - 17%
protected and internal - 13%
private protected - 12%

(These numbers were calculated using "single transferrable vote", so don't try to add them up - that's already implicitly been done).

HOW MANY PEOPLE DISLIKE THE LEADING CANDIDATES:

assembly protected - 61%
restricted - 76%
protected & internal - 79%
protected and internal - 79%
private protected - 77%

(The poll didn't actually ask which candidates were disliked. I made the assumption that if an option isn't in your top five preference, then you don't much care for it. That's where these numbers came from.)



Mads Torgersen will post our discussion about the feature and these results to the C# LDM page - but he's currently presenting at TechEd North America, so it will have to wait until he's back.


What do people make of these numbers?
May 13 at 12:29 PM
madst wrote:
But alas, that name is already taken for a much less useful accessibility level that hardly anyone uses.
Out of curiosity, in the absence of the explicit checks that forbid a method's parameter or return types from having narrower accessibility than the method itself, what would be the effect of declaring such a method? Would it turn the runtime into a pile of goo (thus meaning the checks are necessary to prevent that from happening) or would they have effects that might have been considered confusing, or what? I can think of useful semantics such a thing could mean(*), and I wonder how they compare with what would "naturally" happen.

(*) The semantics I'd like to see would be that a public interface which includes a member with a restricted scope could only be implemented by a class within that scope. Additionally, method whose return type is inaccessible to the caller would be callable, but the only thing that could be done with the return would be to pass it to a method expecting that type. Such semantics would allow code that received a reference to an internal type to know that if every public methods that returns a reference of that type will be returning the only reference of that type, then any method received from outside code will be the only reference to that identified instance. Many operations can be made much more efficient in cases where code knows it holds the only reference to something, but .NET has no facility to statically verify that something is "the only reference to something" even in cases where such static verification would be highly feasible.
May 13 at 12:54 PM
supercat wrote:
madst wrote:
But alas, that name is already taken for a much less useful accessibility level that hardly anyone uses.
Out of curiosity, in the absence of the explicit checks that forbid a method's parameter or return types from having narrower accessibility than the method itself, what would be the effect of declaring such a method? Would it turn the runtime into a pile of goo (thus meaning the checks are necessary to prevent that from happening) or would they have effects that might have been considered confusing, or what? I can think of useful semantics such a thing could mean(*), and I wonder how they compare with what would "naturally" happen.

(*) The semantics I'd like to see would be that a public interface which includes a member with a restricted scope could only be implemented by a class within that scope. Additionally, method whose return type is inaccessible to the caller would be callable, but the only thing that could be done with the return would be to pass it to a method expecting that type. Such semantics would allow code that received a reference to an internal type to know that if every public methods that returns a reference of that type will be returning the only reference of that type, then any method received from outside code will be the only reference to that identified instance. Many operations can be made much more efficient in cases where code knows it holds the only reference to something, but .NET has no facility to statically verify that something is "the only reference to something" even in cases where such static verification would be highly feasible.
Do you mean that, for the outside world, for all intents and purposes, it's an object but for the inside world it's strongly typed. Is that it? Sounds interesting.
May 13 at 1:28 PM
Edited May 13 at 1:29 PM
Given the number of options and the size of the poll, I'm surprised that there was such a clear-cut result.

I'm also surprised at the relative popularity of private protected given that it was almost universally slated on this thread and on SO!

But the C# community has spoken and assembly protected is easily the most popular choice and the least disliked choice to boot.

The advantages I see to this are that:
  1. It's reasonably descriptive.
  2. It's no longer than `internal protected' and doesn't require three words or made-up words.
  3. As in the case of 'internal protected' it can be both reversed and separated without any problem.
The disadvantage is that there's really no difference in meaning between internal protected and assembly protected and we'll therefore have to remember which is the union and which is the intersection of these two access spaces.

From a personal viewpoint, it wasn't included in any of my five preferences. However, I don't dislike it and would be happy if the C# team decides to go with it.
May 13 at 2:35 PM
Edited May 13 at 2:38 PM
I'm also surprised at the results. I tend to think assembly protected is only marginally better than private protected. In some ways it's the worst of both worlds:
  • It's still not clear because it is easily confused with internal protected.
  • It introduces a new word for access modifiers, assembly, while still being verbose.
I still advocate internalandprotected - keep it clear, keep it consistent with VB and IL. Autocomplete will deal with the verbosity issue.

If not internalandprotected, I'd think a new, single keyword is the next best solution. And for that restricted sounds the best, IMHO.

Finally, as I said when the poll was first started, I question doing language design via open internet polls (without any registration even required). We're all programmers, it would be pretty trivial to write something to manipulate the results (not that I'm saying that occurred, just that there's no way to prevent it).
May 13 at 2:53 PM
@MgSame:
"It's still not clear because it is easily confused with internal protected"

It's a lot better than private protected which was initially considered.
Someone who knows C# today and sees private protected just goes "Uh? private and protected makes no sense! neither do private or protected! WTF?". private already has a different meaning, which is very confusing in this context.
Someone who knows C# today and sees assembly protected goes "Uh? that's new let me look it up." and then you learn that assembly protected is a variation that means "protected inside the assembly only".

Yes I agree it's not ideal. I also agree that assembly and internal pretty much mean the same thing in C#, which is a little bit confusing. But if there was a perfect solution nobody came up with it so far, hence the poll.

I for one am OK with assembly protected. No, it's not perfect, but it feels like existing C#, it does not introduce a new keyword, it makes sense and is not misleading to existing C# devs. Given that this is a narrow feature that won't see widespread use, I say go for it. [Full disclosure: it was in my 5 votes]
May 13 at 3:08 PM
MgSam wrote:
I'm also surprised at the results. I tend to think assembly protected is only marginally better than private protected. In some ways it's the worst of both worlds:
  • It's still not clear because it is easily confused with internal protected.
  • It introduces a new word for access modifiers, assembly, while still being verbose.
I still advocate internalandprotected - keep it clear, keep it consistent with VB and IL. Autocomplete will deal with the verbosity issue.

If not internalandprotected, I'd think a new, single keyword is the next best solution. And for that restricted sounds the best, IMHO.
Agreed!
May 13 at 3:10 PM
jods wrote:
@MgSame:
"It's still not clear because it is easily confused with internal protected"

It's a lot better than private protected which was initially considered.
Someone who knows C# today and sees private protected just goes "Uh? private and protected makes no sense! neither do private or protected! WTF?". private already has a different meaning, which is very confusing in this context.
Someone who knows C# today and sees assembly protected goes "Uh? that's new let me look it up." and then you learn that assembly protected is a variation that means "protected inside the assembly only".

Yes I agree it's not ideal. I also agree that assembly and internal pretty much mean the same thing in C#, which is a little bit confusing. But if there was a perfect solution nobody came up with it so far, hence the poll.

I for one am OK with assembly protected. No, it's not perfect, but it feels like existing C#, it does not introduce a new keyword, it makes sense and is not misleading to existing C# devs. Given that this is a narrow feature that won't see widespread use, I say go for it. [Full disclosure: it was in my 5 votes]
assembly protected is better that private protected in the sense that having limb chopped off is better than having it sawed off. :)
May 13 at 3:19 PM
PauloMorgado wrote:
assembly protected is better that private protected in the sense that having limb chopped off is better than having it sawed off. :)
It's better in that it does not use any existing words in a fashion contrary to their previously-established meaning, and since protected is a reserved word there is no way assembly protected might be used (with some other intended meaning) in existing C# code.
May 13 at 3:19 PM
jods wrote:
It's a lot better than private protected which was initially considered.
Someone who knows C# today and sees private protected just goes "Uh? private and protected makes no sense! neither do private or protected! WTF?". private already has a different meaning, which is very confusing in this context.
Someone who knows C# today and sees assembly protected goes "Uh? that's new let me look it up." and then you learn that assembly protected is a variation that means "protected inside the assembly only".
@jods Your example doesn't make sense. When someone unfamiliar sees private protected they will have to look it up. When someone unfamiliar sees assembly protected they will have to look it up or, worse they will assume it means the same as internal protected. private protected at least is weird enough that you know that you don't know what it means. The similarity to internal protected is a huge knock against it, in my opinion.
May 13 at 3:28 PM
MgSam wrote:
@jods Your example doesn't make sense. When someone unfamiliar sees private protected they will have to look it up. When someone unfamiliar sees assembly protected they will have to look it up or, worse they will assume it means the same as internal protected. private protected at least is weird enough that you know that you don't know what it means. The similarity to internal protected is a huge knock against it, in my opinion.
It would be very unusual for a language like C# or even VB.NET to have two very different keywords mean exactly the same thing [in some such cases inherited from VB6, the IDE will replace a form that used to be acceptable in VB6 into a proper VB.NET form]. It is common to have multiple ways of writing something whose semantics are generally quite similar, but which differ in a few ways (e.g. all the varieties of typecast). Someone encountering assembly protected might think that assembly sounds like it's probably related to internal, but should expect that it probably wouldn't mean quite the same thing.
May 13 at 3:40 PM
Edited May 13 at 3:41 PM
@supercat I'd contend that the keywords are not "very different". Most people (rightly so) will associate the word "internal" with "assembly". How often when you're quickly reviewing someone else's code do you give it as much thought as you suggest? There are also lots of existing features that provide redundancy: anonymous delegates/lambdas, multiple array initialization syntaxes, implicit accessibility levels, user-defined operators. Assuming, or reading quickly without thinking, can both lead to mistaken interpretations here.

There is no inherent reason why assembly protected is an "and" while internal protected is an "or". assembly protected will compound the naming mistake made by the C# team when they made internal protected, a mistake which Mads admitted as such in this very thread.
May 13 at 3:49 PM
I prefer the word "intrinsic" instead of private protected and specify accessibility with one word per case:

(a) protected, (b) intrinsic and (c) protectedinternal.

Or, as suggested before:

(a) familiar = the current "protected"
(b) intrinsic = the proposed "private protected"
(c) familiarinternal = the current "protected internal".
May 13 at 3:56 PM
MgSam wrote:
@supercat I'd contend that the keywords are not "very different". Most people (rightly so) will associate the word "internal" with "assembly". How often when you're quickly reviewing someone else's code do you give it as much thought as you suggest? There are also lots of existing features that provide redundancy: anonymous delegates/lambdas, multiple array initialization syntaxes, implicit accessibility levels, user-defined operators. Assuming, or reading quickly without thinking, can both lead to mistaken interpretations here.

There is no inherent reason why assembly protected is an "and" while internal protected is an "or". assembly protected will compound the naming mistake made by the C# team when they made internal protected, a mistake which Mads admitted as such in this very thread.
Exactly. There is no way of two keywords not being confusing. Specially two related words - assembly looks like an alias to internal and vice versa.
May 13 at 3:58 PM
MgSam wrote:
There is no inherent reason why assembly protected is an "and" while internal protected is an "or". assembly protected will compound the naming mistake made by the C# team when they made internal protected, a mistake which Mads admitted as such in this very thread.
Even the terms and and or are hardly unambiguous, since it's unclear whether they apply to the set of things which can access a member, or to the set of categories into which something must belong to have access. Given that the mistake has already irrevokably been made I think the best way forward is to define something which is visibly unlike anything else, with words whose meaning is semantically reasonable, and figure that someone who encounters such a construct with a word they've never seen should look it up.

One concern I have with restricted, or with any other new word used in the absence of a reserved word like protected, is that it may lead to grammatical difficulties. For example, if a feature were added to allow field initializers to be specified as being run after the base constructor, and consequently being allowed to access base members (that's how they work in VB.NET, incidentally), a declaration like
restrict late Foo = someMethod();
could become ambiguous if there existed classes named restrict and late, and if someMethod returned a type which could be cast to either. By contrast, if the syntax were
assembly protected late Foo = someMethod();
the fact that protected is a reserved word would mean that late could not be anything other than a type name.
May 13 at 5:05 PM
supercat wrote:
Even the terms and and or are hardly unambiguous, since it's unclear whether they apply to the set of things which can access a member, or to the set of categories into which something must belong to have access.
I don't think I get your point. As of now, protected internal means protectedORinternal. Meaning that, in order to have access to that type/member, a type needs to be protected (derived from the declaring type) or internal (belong to the same assembly as the declaring type).

That's why I like protectedinternal to mean protectedANDinternal. Meaning that, in order to have access to that type/member, a type needs to be protected (derived from the declaring type) and internal (belong to the same assembly as the declaring type).
May 13 at 5:15 PM
Edited May 13 at 5:15 PM
supercat wrote:
Even the terms and and or are hardly unambiguous, since it's unclear whether they apply to the set of things which can access a member, or to the set of categories into which something must belong to have access. Given that the mistake has already irrevokably been made I think the best way forward is to define something which is visibly unlike anything else, with words whose meaning is semantically reasonable, and figure that someone who encounters such a construct with a word they've never seen should look it up.
It's far less ambiguous because the usage of "and" and "or" come directly from the actual IL and will correspond with what VB is doing. Also, as I've argued before, even if its not technically correct, most people think of modifiers as restricting rather than widening. This is what has led to the frequent misunderstanding of protected internal. Under that thought process "and" must mean that it is restricted to whatever the arguments of the "and" are.

I think the language should be designed to do the right thing for the naive programmer whenever possible- the pit of quality.
May 13 at 5:46 PM
MgSam wrote:
It's far less ambiguous because the usage of "and" and "or" come directly from the actual IL and will correspond with what VB is doing. Also, as I've argued before, even if its not technically correct, most people think of modifiers as restricting rather than widening.
Are there any situations other than "protected internal" when modifiers actually "widen", rather than "replace"? I would think it would have been more natural to regard modifiers like constructor overloads; in the absence of any, a default is assumed, but adding the first one will negate that default. The only case I can think of where a modifier would act relative to an existing access level would be in constructs like public foo { get; private set; } in which case the effect is definitely narrowing.
May 13 at 9:12 PM
An important point of difference between internal protected and assembly protected is that, unlike internal, assembly has no meaning on its own as an access modifier.

It's therefore illogical to think that assembly protected might mean either the union or intersection of the assembly and protected access spaces because there's no such thing as assembly access.

If instead one thinks of assembly as simply modifying protected access, then what else could it reasonably mean than protected within the current assembly?

So, if we think of the proposed keyword assembly in the above terms, it starts to look more appropriate in expressing what we need here.

internal protected means, of course, the union of the internal and protected access spaces and always will mean that if backwards compatibility is to be maintained.
May 13 at 11:24 PM
supercat wrote:
The only case I can think of where a modifier would act relative to an existing access level would be in constructs like public foo { get; private set; } in which case the effect is definitely narrowing.
You need to apply a more restrictive modifier, but that modifier does not restrict the global property modifier - it overrides it.
May 13 at 11:26 PM
vulpecula wrote:
An important point of difference between internal protected and assembly protected is that, unlike internal, assembly has no meaning on its own as an access modifier.

It's therefore illogical to think that assembly protected might mean either the union or intersection of the assembly and protected access spaces because there's no such thing as assembly access.

If instead one thinks of assembly as simply modifying protected access, then what else could it reasonably mean than protected within the current assembly?

So, if we think of the proposed keyword assembly in the above terms, it starts to look more appropriate in expressing what we need here.

internal protected means, of course, the union of the internal and protected access spaces and always will mean that if backwards compatibility is to be maintained.
What's the meaning of the internal modifier?
May 14 at 1:13 PM
PauloMorgado wrote:
What's the meaning of the internal modifier?
You defined internal yourself in your penultimate post as meaning:

"belonging to the same assembly as the declaring type".

The point I was trying to make is that, unlike internal, assembly has no technical meaning on its own because it's not an access modifier.

Anyone looking at assembly protected for the first time might therefore reasonably (and correctly) guess that it means protected within the current assembly.

They'd be unlikely to think that it means accessible within the currently assembly OR to derived types because that's what internal protected already means and it's hardly the most natural of interpretations in any case.
May 14 at 1:28 PM
vulpecula wrote:
PauloMorgado wrote:
What's the meaning of the internal modifier?
You defined internal yourself in your penultimate post as meaning:

"belonging to the same assembly as the declaring type".
So, you acknowledge that internal relates to assembly.
The point I was trying to make is that, unlike internal, assembly has no technical meaning on its own because it's not an access modifier.
internal IS an access modifier.
Anyone looking at assembly protected for the first time might therefore reasonably (and correctly) guess that it means protected within the current assembly.
What someone looking at assembly protected for the first time guess depends where she/he is coming from. I'd be extremely confused.
They'd be unlikely to think that it means accessible within the currently assembly OR to derived types because that's what internal protected already means and it's hardly the most natural of interpretations in any case.
I wouldn't know what to think at all.
Coordinator
May 14 at 1:39 PM
PauloMorgado wrote:
What someone looking at assembly protected for the first time guess depends where she/he is coming from. I'd be extremely confused.
Maybe this thread should be titled "assembly protected is an abomination"
Developer
May 14 at 2:57 PM
We are unlikely to add this new protection level at this time, mainly because we are unable to find a good syntax.
May 14 at 3:02 PM
That would be a shame, especially since it's already implemented and often requested :(
Pick anything your team believes in, people will get used to it anyway.
May 14 at 3:03 PM
@nmgafter I think deferring the problem doesn't solve anything. You guys are the language designers, you should ultimately just take people's opinions under advisement and make the decision. If you drop every feature when some people complain about them, then there won't be any features that get added.

It will totally suck if VB gets this feature and C# does not because of disagreement over the name. I'd rather have a non-ideal name then no name at all. restricted seems like a mostly non-controversial 2nd place; I'm willing to compromise and live with it.
May 14 at 3:03 PM
lwischik wrote:
PauloMorgado wrote:
What someone looking at assembly protected for the first time guess depends where she/he is coming from. I'd be extremely confused.
Maybe this thread should be titled "assembly protected is an abomination"
Or "anything other than protectedinternal is an abomination". :)
May 14 at 4:10 PM
Edited May 14 at 4:11 PM
nmgafter wrote:
We are unlikely to add this new protection level at this time, mainly because we are unable to find a good syntax.
I sense that agreement may be breaking out that WE DO WANT this feature, whatever it's called.

Although I've tried to defend assembly protected given its popularity in the poll, I have to admit that the words assembly and internal mean much the same thing which is why I didn't vote for it in the first place.

So I agree with MgSam - just go for the least controversial choice of restricted which was second in the poll and is what Mads suggested himself when he was arguing for a single keyword solution.

We'll soon get used to it :)
May 14 at 4:59 PM
@nmgafter: how about "intrinsic"?
May 14 at 6:22 PM
Edited May 14 at 6:23 PM
vulpecula wrote:
So I agree with MgSam - just go for the least controversial choice of restricted which was second in the poll and is what Mads suggested himself when he was arguing for a single keyword solution.
Would there be any danger of a single context-sensitive (non-reserved) keyword interacting badly with any other present or future context-sensitive keyword in field declarations? I would think assembly protected could be parsed more easily and reliably, given that general identifiers may not appear immediately before protected.

Are there any present cases in which a declaration nonReservedWord1 nonReservedWord2 nonReservedWord3; or nrw1 nrw2 nrw3 = expression; would be a valid declaration? If not, is the new feature sufficient to justify precluding the possibility of having nrw2 or nrw3 be a context-sensitive keyword without introducing ambiguity?
May 14 at 6:45 PM
I would be happy to change my vote to either assembly protected or restricted in order to get this feature in. My top choices weren't even in the list to begin with.

Frankly, if deprecating internal protected isn't in the cards, then I feel any proposal will be inherently confusing (and require a tour of the documentation) no matter which English words are chosen, but that's just how it is when you are working around a historical design decision. I don't see much value in brainstorming more possible adjectives. Not having functional parity with VB just seems wrong, plus I do see legitimate scenarios for using this feature. There are some [admittedly minority] problem spaces where inheritance is beneficial but external extensibility is not - enforcing compliance with an industry or organizational standard comes to mind.

Given that assembly and internal are synonyms in C# [as others have pointed out], and given that restricted directly addresses the confusion over whether additional keywords are widening or narrowing, I slightly lean towards the restricted option.
May 14 at 6:59 PM
supercat wrote:
Would there be any danger of a single context-sensitive (non-reserved) keyword interacting badly with any other present or future context-sensitive keyword in field declarations? I would think assembly protected could be parsed more easily and reliably, given that general identifiers may not appear immediately before protected.

Are there any present cases in which a declaration nonReservedWord1 nonReservedWord2 nonReservedWord3; or nrw1 nrw2 nrw3 = expression; would be a valid declaration? If not, is the new feature sufficient to justify precluding the possibility of having nrw2 or nrw3 be a context-sensitive keyword without introducing ambiguity?
I'd assumed that Mads would have considered potential conflicts with other contextual keywords before suggesting a single (presumably contextual) keyword in the first place.

I suppose if you had a class called 'restricted' in scope, field declarations such as this would look odd:

restricted restricted; // private field (by default) of type 'restricted' called 'restricted'
restricted restricted restricted; // restricted field of type 'restricted' called 'restricted'

but, if you follow the guidelines, types shouldn't begin with a lower case letter anyway and identifiers which conflict with contextual keywords are best avoided unless the context would preclude the use of the keyword in question.

One good thing about private protected is that it doesn't have these problems and can't be confused with internal protected even if it's unclear what it actually means.
May 14 at 7:10 PM
I've been watching this thread with considerable interest over the last couple of weeks. Great to see so much passionate debate about future C# features :D

In short, I think that there are times where adding a new keyword makes a great deal of sense and I think this is one of those times.

I appreciate the desire to not bloat C# with unnecessary new keywords. I am all for re-using keywords that validly help developers concisely articulate the specific and unambiguous semantic meaning of a piece of code. I am not necessarily averse to combining two or more keywords to describe new semantics, but I believe that doing so should generally be for rare, infrequently-typed scenarios, not pretty main-line scenarios like this one.

C# is already pretty 'verbose' and descriptive. Having spent some time playing with and appreciating F#'s terseness and seeing some of the other brevity-oriented new features for C#, I'd prefer not to build-in a new syntax that increases C#'s code footprint further still.

Like @vulpecula and others, while I think 'cloaked' would have been fun, I too am leaning heavily towards 'restricted'.
May 14 at 7:38 PM
vulpecula wrote:
I suppose if you had a class called 'restricted' in scope, field declarations such as this would look odd:

restricted restricted; // private field (by default) of type 'restricted' called 'restricted'
restricted restricted restricted; // restricted field of type 'restricted' called 'restricted'

but, if you follow the guidelines, types shouldn't begin with a lower case letter anyway and identifiers which conflict with contextual keywords are best avoided unless the context would preclude the use of the keyword in question.
Certainly I wouldn't suggest that a programmer should create a type called restricted, but think it's generally good to avoid requiring too much look-ahead to figure out what a construct means. I'm not saying that languages should be designed to be LL(1) parseable, but I favor languages which use tokens and reserved words to nail down grammatical structures. For example, if in a place where a statement is required a parser encounters a non-reserved word followed by "return", it won't have to look a the non-reserved word to know that the statement should be processed as a "yield return". Such handling should of course ensure that the non-reserved word is, in fact, "yield", but the parser doesn't need to worry about that.

If the compiler already has the necessary logic to handle the meaning of
restricted restricted() { throw new Exception(); }
in the different scenarios where it could legally occur, I'd be impressed. If handling such cases would require adding complexity, though, I think a syntax which didn't require such complexity would be better.
May 14 at 7:42 PM
BitCrazed wrote:
Like @vulpecula and others, while I think 'cloaked' would have been fun, I too am leaning heavily towards 'restricted'.
My first preference was actually sheltered but glad to see that, like me, you're climbing onto the restricted bandwagon now :)
Coordinator
May 14 at 8:11 PM
vulpecula wrote:
I'd assumed that Mads would have considered potential conflicts with other contextual keywords before suggesting a single (presumably contextual) keyword in the first place.
No, not fully... We're writing our thoughts here in the open as we have them, rather than staying silent until we've ironed out all the details.

It's extremely hard to reason about whether contextual keywords are okay. In general, you can't rely on symbol-resolution to inform how the compiler should parse some text.

Why was the "async" contextual modifier okay? It's possible that it was only through the happy coincidence that you can't have an async constructor. Haven't yet thought through the details on this point.
May 14 at 9:46 PM
lwischik wrote:
Why was the "async" contextual modifier okay? It's possible that it was only through the happy coincidence that you can't have an async constructor. Haven't yet thought through the details on this point.
As long as you follow C# conventions, keywords will always be all lowercase and type names, property names and method names will always be CamelCase.
May 14 at 9:53 PM
I think in general MS spends too much time worrying about corner cases like this. If I'm upgrading my application to a new version of a language, I shouldn't be shocked if there are some small breakages (especially for poorly named methods like "async" or "restricted"). You're upgrading, you should be prepared to make minor modifications to the source.
May 14 at 10:32 PM
MgSam wrote:
I think in general MS spends too much time worrying about corner cases like this. If I'm upgrading my application to a new version of a language, I shouldn't be shocked if there are some small breakages (especially for poorly named methods like "async" or "restricted"). You're upgrading, you should be prepared to make minor modifications to the source.
Is restricted sufficiently better than any formation which uses at least one reserved word to justify any additional compiler complexity that may be associated with processing it?
I think in general MS spends too much time worrying about corner cases like this.
The best way to avoid spending time dealing with corner cases is to avoid needlessly creating them.
May 15 at 5:46 PM
restricted is ambiguous, unspecific, kinda silly...

I would prefer packaged: it's meaning is almost extremely obvious.
Or if you don't want new keyword, then internalprotected.
And if you can't decide just give some attribute until you do. That's easy.
May 15 at 7:07 PM
Edited May 15 at 9:44 PM
Alekdias wrote:
restricted is ambiguous, unspecific, kinda silly...

I would prefer packaged: it's meaning is almost extremely obvious.
Or if you don't want new keyword, then internalprotected.
And if you can't decide just give some attribute until you do. That's easy.
packaged conveys roughly the same meaning as internal, but says nothing about protected, so it's misleading.
OTOH, you can't guess what restricted means, so you have to look it up and learn what it means, which is better IMO.
May 15 at 7:27 PM
intrinsic
May 15 at 9:15 PM
Ultimately, THIS ---> "you have to look it up and learn what it means" (@tom103).
May 16 at 4:26 AM
How about "nucleated"?
May 21 at 12:23 AM
I'm personally feeling that the thesaurus debates are going nowhere - none of the proposals have seemed any more or less intuitive to me. I agree with this:
BitCrazed wrote:
Ultimately, THIS ---> "you have to look it up and learn what it means" (@tom103).
Absolutely correct. Plus, I think the primary flaw in all of the "pick a brand new adjective" approaches is that they don't result in deprecating internal protected. So, I find myself gravitating toward the second message in this whole discussion:
jods wrote:
I think you could just as well expose it as an attribute on the field / method (i.e. coders mark the field protected and slaps an InternalOnly attribute on it). That wouldn't be the first time attributes are used to fiddle with internal visibility (I'm thinking of the InternalsVisibleTo assembly attribute).
I think that's my vote at this point [or, if naming debates ensue, go with FamilyAndAssemblyAttribute to match the CLI naming convention]. It could be a compile error if protected wasn't present or if the internal or public keywords were also explicitly present.

By not being directly in the grammar it should appease those who think the whole feature is questionable [in spite of it being part of both the CLR and VB.NET], but it still provides functional parity with VB so that a .NET library doesn't have to be written in VB to have this functionality.

Any chance of a new vote limited to the attribute approach, just to see if any consensus emerges?
May 21 at 8:54 AM
btjagilent wrote:
I think that's my vote at this point [or, if naming debates ensue, go with FamilyAndAssemblyAttribute to match the CLI naming convention]. It could be a compile error if protected wasn't present or if the internal or public keywords were also explicitly present.
If the option is to go with an attribute (I don't like it because it's an enormous change on the way you write/read code), I would favor a AccessAttrubute with an enumerable for the possibilities.

But, frankly, if the Visual Basic folks could agree with ProtectedAndFriend (for FamilyAndAssembly) and ProtectedOrFriend (for FamilyOrAssembly - alias to Protected Friend or vice versa) (VB LDM 2014-03-12 ), why can't we just apply C# rules to it and simply go with protectedandinternal (for FamilyAndAssembly) and protectedorinternal (for FamilyOrAssembly - alias to protected internal or vice versa)?

I still prefer protectedinternal for FamilyAndAssembly!
May 21 at 9:20 AM
It could be a compile error if protected wasn't present or if the internal or public keywords were also explicitly present.
The problem with attributes is that the InternalsVisibleTo taken as argument widens the accessibility, so the respective accessibility keywords provide everything they promise. However, the FamilyAndAssembly is a restricting attribute on protected, so protected would actually not deliver what it is supposed to.
But, frankly, if the Visual Basic folks could agree with ProtectedAndFriend (for FamilyAndAssembly) and ProtectedOrFriend (for FamilyOrAssembly - alias to Protected Friend or vice versa) (VB LDM 2014-03-12 ), why can't we just apply C# rules to it and simply go with protectedandinternal (for FamilyAndAssembly) and protectedorinternal (for FamilyOrAssembly - alias to protected internal or vice versa)?
Visual Basic has long tradition gluing words together using camel casing, like AndAlso, OrElse, ByRef, ByVal etc... while C# does not.
May 21 at 11:06 AM
Edited May 21 at 11:10 AM
I also think an attribute is better suited for this, increasing the syntax is unnecessary for what it's worth, and given that there's already so much confusion around internal protected anyway, it needs to be made clearer.

I'd suggest an attribute for both forms, with an argument for how they should be combined, with the default argument as union for compatibility with the existing situation. It would be optional to use the "internal protected" keyword in both cases where the attribute is present, but also redundant, and not recommended.
public enum AccessCombiner {
    Union, Intersect 
}
[AttributeUsage(AttributeTargets.Class|
                AttributeTargets.Constructor|
                AttributeTargets.Delegate|
                AttributeTargets.Enum|
                AttributeTargets.Event|
                AttributeTargets.Field|
                AttributeTargets.Interface|
                AttributeTargets.Method|
                AttributeTargets.Property|
                AttributeTargets.Struct)]
public class InternalProtectedAttribute : Attribute {
    public InternalProtectedAttribute(AccessCombiner op = AccessCombiner.Union) { }
}

//mirror existing behavior
[InternalProtected] 
class Test_InternalOrProtected { } 

//new behavior
[InternalProtected(AccessCombiner.Intersect)]
class Test_InternalAndProtected { }
Perhaps you could reduce the argument to a bool if it has a descriptive enough name.
May 21 at 11:16 AM
JanKucera wrote:
Visual Basic has long tradition gluing words together using camel casing, like AndAlso, OrElse, ByRef, ByVal etc... while C# does not.
The C# tradition is to glue them all in small casing, thus protectedinternal, protectedandinternal and protectedorinternal.
May 21 at 12:17 PM
Edited May 21 at 12:19 PM
PauloMorgado wrote:
The C# tradition is to glue them all in small casing, thus protectedinternal, protectedandinternal and protectedorinternal.
Ok, I can think of foreach, are there any other ones? If not that's hardly a tradition.

I'd rather say the tradition is to try to express things with single words, not compound ones. A good illustration of that fact is that C# team choose protected internal over protectedinternal.

Personnally I think that lowercase compound words are quite unreadable, especially long ones. protectedandinternal, protectedorinternal ? Ugh :(
May 21 at 12:44 PM
jods wrote:
PauloMorgado wrote:
The C# tradition is to glue them all in small casing, thus protectedinternal, protectedandinternal and protectedorinternal.
Ok, I can think of foreach, are there any other ones? If not that's hardly a tradition.

I'd rather say the tradition is to try to express things with single words, not compound ones. A good illustration of that fact is that C# team choose protected internal over protectedinternal.

Personnally I think that lowercase compound words are quite unreadable, especially long ones. protectedandinternal, protectedorinternal ? Ugh :(
@jods This has been mentioned already in this thread, so I suggest you read the rest of it, but C# has many multi-word modifiers:

foreach
namespace
orderby
readonly
sizeof
typeof
stackalloc
nameof

I agree they're a little verbose at first, but you'd get used to them in short order, and they're not the kind of thing you use everyday anyway. If I had to guess I'm sure people would have a lot of the same reservations about namespace if the language was just being designed and open to community comment. Yet its something no one gives a second thought to now.
May 21 at 12:56 PM
@MgSam:
indeed there are a few more than I thought of. You added a few extras as Namespace is a single word and Read-only contains a dash.

But you are right there are foreach, orderby, sizeof, typeof, stackalloc and nameof (not yet -- soon).
sizeof and stackalloc are seldom seen (outside interop and unsafe code I guess), but I could have thought of typeof and orderby ;)

Anyway... You'd notice that they all are pretty short. Except for stackalloc they all are 6 or 7 characters long. I still have a problem introducing two 20 characters long new reserved words. That only differ by 3 letters. And that are going to get slapped to already long lines (consider protectedandinternal readonly Dictionary<string, Metadata> metadataCache = new Dictionary<string, Metadata>();).
May 21 at 7:04 PM
jods wrote:
But you are right there are foreach, orderby, sizeof, typeof, stackalloc and nameof (not yet -- soon).
Also note that most of them carry the meaning in one word only with added preposition, while protectedandinternal have 3 words with equally important meaning.
Jun 27 at 4:36 PM
Is it out of the question to make a breaking change on the definition of protected [or] internal to protected [and] internal? Otherwise, we'd be adding another misnomer (private protected) on top of an existing misnomer (protected [or] internal). I think it more important that we consider the long term impact to the platform rather than what is convenient today.
Jun 27 at 5:48 PM
Are you proposing to break Windows Forms (and probably WPF as well) and ASP.NET?
Jun 27 at 6:53 PM
PauloMorgado wrote:
Are you proposing to break Windows Forms (and probably WPF as well) and ASP.NET?
Out of curiosity, in the existing corpus of C# code, how does the frequency of usage of internal protected compare with protected internal? I think the ideal thing from a language perspective would have been to have one of those be the union and the other be the intersection. I don't see any general trend of "adding adjectives widens access"--in general, I see adjectives as replacing a default access specifier, and presently there is no explicit combination of adjectives other than protected and internal.
Jun 28 at 6:43 AM
Are people (still!) seriously making suggestions like:

"Let's make protectedinternal mean something different to protected internal"

"Let's make protected internal mean something different to internal protected"

"Let's make protected internal in C# 5 mean something different to protected internal in C# 6"

Because these suggestions are insane!
Jun 28 at 12:31 PM