35

I'd like to create an internal auto-property:

internal bool IP { get; protected internal set; }

I thought it would be possible to make the setter protected or protected internal - but I always get the error accessibility modifier must be more restrictive than the property. Isn't that the case? Private does not help me, here.

EDIT:
The question is: How do I implement an auto-property with a internal getter and a protected setter?

Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222
tanascius
  • 53,078
  • 22
  • 114
  • 136
  • 25
    Your error is in thinking of the modifiers as _increasing_ restrictions. The modifiers in fact always _decrease_ restrictions. Remember, things are "private" by default; only by adding modifiers do you make them less restricted. – Eric Lippert Jun 30 '09 at 16:22
  • 1
    +1 - eric lippert you always put it in the best way possible – JonH Jan 07 '10 at 19:20
  • 1
    Actually, the **combination** of modifiers is _decreasing_ restrictions. Only **setting** a modifier is indeed _increasing_ the restrictions such as `public bool IP{get; private set;}` – Dani Jul 09 '14 at 14:16

8 Answers8

53

It's effectively protected or internal, not and. It's accessible both by derived classes and types in the same assembly. It's a common misconception to think protected internal means accessible only to derived classes in the same assembly.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 1
    OK, how do I make the getter internal and the setter protected? – tanascius Jun 30 '09 at 14:11
  • 2
    You can't. Getter/setter access modifier should be a proper subset of the property access modifier. – Mehrdad Afshari Jun 30 '09 at 14:13
  • 3
    My problem was really the misunderstanding that protected internal means protected AND internal - thanks for pointing that out. – tanascius Jun 30 '09 at 14:20
  • I think your phrasing is VERY confusing. The use of AND and OR do not help clarify the issue. `protected internal` means that it is accessible by all that would be able to access `protected` AND all that would be able to access `internal` – DevinB Jun 30 '09 at 15:05
  • 2
    @devinb: My first sentence might be. But the second sentence clarifies the issue: "It's accessible both by derived classes and types in the same assembly. " – Mehrdad Afshari Jun 30 '09 at 15:07
  • 1
    Yes, you're correct. I meant my critique only to your first sentence. – DevinB Jun 30 '09 at 15:12
30

At the .NET level, there are two similar but distinct access levels:

  • FamilyAndAssembly: more restrictive than either protected or internal
  • FamilyOrAssembly: less restrictive than either protected or internal

"protected internal" in C# means FamilyOrAssembly; there's no modifier for FamilyAndAssembly.

So, your protected internal setter is less restrictive than the internal overall property. What you could do is:

protected internal bool IP { internal get; set; }

But then your setter is less restricted than your getter, which is odd...

Another (somewhat equivalent) alternative is:

internal bool IP { get; set; }

protected void SetIP(bool ip)
{
    this.IP = ip;
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • OK, my solution could be a internal readonly property with a protected backing-field. – tanascius Jun 30 '09 at 14:17
  • Or your equivalent alternative with a private setter would do the job, too. – tanascius Jun 30 '09 at 14:25
  • It occurs to me, (months later of course) that the setter is still accessible "internally" which is in some ways less restrictive than protected. To fully make it an internal getter and a protected setter, you would have to have protected void SetIP(bool value) and internal bool GetIP() and then have a private bool _IP – DevinB Sep 28 '09 at 16:57
  • So did you just say the CLR has an entire access restriction level of `FamilyAndAssembly` that is not consumable in C# without resorting to IL magic etc? – Chris Marisic May 02 '12 at 16:14
  • @ChrisMarisic: I don't know what happens if you try to consume it. It may be like some prohibited generics constraints - the C# compiler will *obey* it but doesn't give any way of *expressing* it in your own code. – Jon Skeet May 02 '12 at 16:22
  • @JonSkeet similar to how you can't constraint type T to an enum normally in C#? – Chris Marisic May 02 '12 at 18:29
  • @ChrisMarisic: Yes - that's exactly the example I was thinking of. – Jon Skeet May 02 '12 at 18:48
  • Since C# 7.2, the "private protected" accessibility level is available for FamilyAndAssembly (see https://stackoverflow.com/questions/22856215). – Erlend Graff May 11 '18 at 13:17
7

Considering what Jon Skeet mentioned (and user59808's comment), wouldn't this achieve the desired result?

protected internal bool IP { get; protected set; }

void
  • 769
  • 6
  • 7
5

I would consider this cheating, since Eric Lippert is on SO himself, but he wrote an excellent blog post that considers this issue.

Why Can't I Access A Protected Member From A Derived Class, Part Three

Ultimately, his answer is largely the same as those given by the posters here, but he ads some interesting reasoning behind the desgin of the language and the implementation of these features.

DevinB
  • 8,231
  • 9
  • 44
  • 54
3

protected internal is less restrictive than either protected or internal because it allows both its subclasses (protected) and anything in the same assembly (internal) to access something.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
1

protected internal means visible to classes in the same assembly, or to classes deriving from the containing class - in other words it is visible to those meeting the internal requirements OR the protected requirements, not AND. There is no access modifier meaning protected AND internal in this way.

David M
  • 71,481
  • 13
  • 158
  • 186
1

protected internal means protected OR internal, not protected and internal. So scope is limited to the same assembly OR derived classes, not necessarily both.

Brian Rudolph
  • 6,142
  • 2
  • 23
  • 19
0

accessibility modifier must be more restrictive than the property

Internal is more restrictive that protected: because protected things can be seen (by subclasses) outside the assembly.

The compiler is saying that there's no sense in saying that set is protected (i.e. visible to subclasses outside the assembly), when the whole IP property is internal (i.e. invisible outside the assembly).

ChrisW
  • 54,973
  • 13
  • 116
  • 224