.NET Backend

private protected in C#?

A few days ago I watched a very interesting talk from NDC given by Jon Skeet, Kathleen Dollard and Rob Conery. Around 41:15 minute Kathleen said something very interesting about protected internal:

[…] if you say protected internal then that item is visible in any protected class, in any other class within that DLL […]

At first, I was like „what the hell is she talking about?”. That was because in my option her definition was simply wrong since it says that protected internal member can be accessed from a class that is not a concrete type. This is crazy, right? We, all know that protected internal means that the member can be accessed only from a class that inherits from a type AND if it’s is in the same assembly! These are the basics of C# that everyone should now. But, at some point, I felt not 100% sure, so I decided to stop the video and try it out in VS Code.


protected internal in C#

The code I wrote was the following one:


    public class Class1

    class A
        protected internal int Value => 1;

    class B : A { }

    class C
        void Test()
            var b = new B().Value;


That was the easiest code that could prove that I was right. I hit the semicolon after calling protected internal property… and I waited for an error. But, nothing happened. That was the second time I was like „WAT ?!”. Well, I thought that maybe there is some issue with my editor so I tried something different. Consider the following code:


protected int A { get; protected set; }


This would not compile since the accessibility modifier on the setter must be more restrictive than property. So, I came up with the following code:


protected int A { get; protected internal set; }


This time I got the error:

„The accessibility modifier of the ‚Test.A.set’ accessor must be more restrictive than the property or indexer”.

At this point, I knew two things:  Kathleen was right, and I don’t know C# as good as I thought. Just to make it sure, I visited MSDN and I read the description of protected internal modifier:

The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly.

There is one more interesting thing related to protected internal that proves the above. If you override a virtual method from inherited type then the accessibility modifier have to be exactly the same. Otherwise, you get the following error:

[…]… cannot change access modifiers when overriding ‚<modifier>’ inherited member […]

As you probably guess, this does not apply to protected internal. Well, at least partially:



    public class Class1Lib1
        protected internal virtual void Test() { }

    class Class2Lib1 : Class1Lib1
        protected internal override void Test()


    public class Class1Lib2 : Class1Lib1
        protected override void Test()


So, if you override a virtual method in the same assembly, then you can leave it as protected internal. Thing got strange when it’s another DLL, then modifier needs to be restricted to protected. Actually, that makes sense, because otherwise, we could do this infinitely.


private protected in C#?

Right after I was completely ashamed by Kathleen’s definition I continued watching the video. Soon after she mentioned something very interesting:

Would it be nice to have the inverse of it. […] We could have I want the only people I want to be able to see this is I wanted to be within this hierarchy to derive from this class and also within this assembly. […] it’s been in .NET since the very first release in 2000, was in the alpha. Do you know why you don’t have it? […] Because we can’t name it.

So, in the nutshell something that I understood as the protected internal exists in .NET, but it’s not supported by C# because we can’t name it! Then, she mentioned that it could be something like „private protected„. Wow. That was a very interesting thing, so I wanted to dig a little more dipper.

Before we move further, let’s take a look at accessibility modifiers in the Intermediate Language (IL):

  • private -> Private
  • public -> Public
  • internal -> Assembly
  • protected -> Family
  • protected internal – FamORAsem

So, you see now that even in IL that’s OR not AND. So far, so good. But, if you have ever played with C# reflection a little, you probably now MethodAttributes enum. Let’s inspect that:


namespace System.Reflection
	public enum MethodAttributes
		PrivateScope = 0,
		ReuseSlot = 0,
		Private = 1,
		FamANDAssem = 2,
		Assembly = 3,
		Family = 4,
		FamORAssem = 5,
		Public = 6,
		MemberAccessMask = 7,
		UnmanagedExport = 8,
		Static = 16,
		Final = 32,
		Virtual = 64,
		HideBySig = 128,
		NewSlot = 256,
		VtableLayoutMask = 256,
		CheckAccessOnOverride = 512,
		Abstract = 1024,
		SpecialName = 2048,
		RTSpecialName = 4096,
		PinvokeImpl = 8192,
		HasSecurity = 16384,
		RequireSecObject = 32768,
		ReservedMask = 53248


If you didn’t spot that, the fourth item is called „FamANDAssem” which got me a clear sign that I could create private protected method. So, what I did was modifying listing presented in the book titled „C# 6.0 in a Nutshell” which presented the way of generating types dynamically:


            var appDomain = AppDomain.CurrentDomain;
            var assemblyName = new AssemblyName("PrivateProtected");
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

            var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule", "PrivateProtected.dll");

            var typeBuilder = moduleBuilder.DefineType("MyDynamicType", TypeAttributes.Public);

            var methodBuilder = typeBuilder.DefineMethod("ILTest", MethodAttributes.FamANDAssem, null, null);
            var gen = methodBuilder.GetILGenerator();

            gen.EmitWriteLine("I'm private protected!");
            var type = typeBuilder.CreateType();

            object o = Activator.CreateInstance(type);
            type.GetMethod("ILTest", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(o, null);


What it does is it creates a class called MyDynamicType which contains one method called ILTest. The method has a void return type and it prints on console text „I’m private protected”. Please notice that inside DefineMethod I declared that the accessibility modifier should be FamANDAssem. At the end of the program, I created an instance of this type and invoked a method using reflection. The result?



I did it! I invoked private protected method in C#! Well, sort of 😀 But this solution did not allow me to inspect the IL. So I added the following line:




The above line saves generated type into DLL which is stored on the computer. So, right after that, I open it using dotPeek:



As you see dotPeek presented the method as protected internal but when you look at the actual IL you can notice that the modifier is FamANDAssem just like expected. But, wait! Since it’s a DLL it basically means it can be included into any project as a reference. I did it and I created a class which inherited from MyDynamicType class. Then inside of the constructor, I wanted to check whether I have an access to ILTest method:



After I navigated to the class declaration I couldn’t see it:



So, to sum it up. Protected internal means in a nutshell protected OR internal. IL supports AND version (private protected) but the C# itself not.

I’m just wondering whether language designers didn’t get into popular „naming” issue. I’d personally expect both modifiers put together to be more restrictive than each one separate. What are your thoughts about it? Please share in comments.