21

As you may already know, the .NET Framework's protected internal access modifier works in a strange way: It doesn't mean the class is protected AND internal, it says the class is protected OR internal; that is, the modified class or member can be accessed from whitin the same assembly as well as from the same hierarchy.

So, knowing this: When would you use it? Can you give an example? Is there a good, illuminating usage example inside .NET Base Class Library?

Pablo Marambio
  • 1,562
  • 1
  • 15
  • 29
  • I didn't know that. I always thought it was AND. – Bob King Oct 15 '08 at 15:36
  • It's what you imagine when you first read it. I think anyone might guess the same way. – Pablo Marambio Oct 15 '08 at 15:51
  • Yeah, it catches everyone out the first time, I think. – Jeff Yates Oct 15 '08 at 15:52
  • 1
    The AND/OR logic is a bit confusing. In C# members are private by default, and you can open access as needed. Public gives all access, protected gives access to derived classes, and internal gives access to all classes in the same assembly. By this reasoning, protected internal is protected AND internal (you give access to both derived classes and classes in same assembly). Most people think of it the other way around (adding restrictions instead of taking them away). – Lucas May 21 '09 at 03:59
  • 3
    [The mandatory link to Eric Lippert's post on this topic](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). – Roman Starkov Jun 06 '11 at 16:11
  • I think Lucas's logic is a bit off. `protected` and `internal` each describe a set of entities who can access the member. It is unreasonable to say that `internal` semantically describes the set who *can't* access the member! So `protected internal` refers to the union OR not intersection AND of those two sets. It doesn't really matter what you view as the default access level. – Matthew Jul 11 '15 at 20:46

3 Answers3

10

I have rarely needed to use this access modifier combination as I think that in all but the most extreme circumstances, it's an indicator of poor design. However, sometimes it is necessary to have helper classes like type converters and editors access the method inside your assembly, but only allow derived classes to access it in other use cases.

An example might be a call that turns a type into a string for the type converter. ToString() generally isn't used for this purpose so you might have a ToPersistableString() call that you want your type converter to use, so you make it internal. Then you decide that people deriving from your class may well want to use this call as part of their own persistence scheme for their derived class so you make it protected as well.

.NET Framework Use
AccessibilityNotifyClients on Control is protected internal. Using Reflector, I can see that this was done so that the CheckedItemCollection of CheckListBox could access it when changing checked states.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
  • This answer is hard to understand; I don't really see what your type converter is doing or why it's doing it. First, it will only work with types that have `ToPersistableString()` defined (ie. virtually none). Second, why would you convert the type name into a string instead of using `typeof`, or get the name via `.GetType().ToString()`? And why call it `PersistableString` and not `TypeNameString` - what is persistable about it? If you could clarify this and bit and provide a code sample of your example type converter I will upvote this answer. – Jez May 05 '12 at 08:36
  • 1
    @Jez: It's an example. It's merely stating that you may have two types internally (your type and its converter) that need to access the method, but you may also want to be able to override that method to extend it in derived classes. Type converters allow you to convert to and from different types: `ToPersistableString` would provide a string version of the type to allow the type to be persisted to a string. No one is converting the type name here. For more information on type converters, see MSDN (http://msdn.microsoft.com/en-us/library/System.ComponentModel.TypeConverter.aspx) – Jeff Yates May 07 '12 at 13:57
2

I've used it for internal methods that you wanted to be able to use in a separate name space for unit testing, the unit test name space contained a subclass of the class. which allowed the protected methods to be accessed.

That said there is an argument to make everything public for unit testing.

Omar Kooheji
  • 54,530
  • 68
  • 182
  • 238
  • Do you mean namespace or assembly? You might want to consider the InternalsVisibleToAttribute to overcome the testing problem [assembly: InternalsVisibleTo("Your.Tests")] – Mark Powell Mar 28 '14 at 11:17
  • I meant namespace, if I have to unit test a class with internal stuff I create a new project but make the name space the same so I can access them. I know it's probably not best practice but it works, and the unit tests aren't compiled into my deployment. I'll look into that attribute though it looks interesting. – Omar Kooheji Mar 28 '14 at 11:26
2

I would like to add an example from ASP.Net MVC framework:

public abstract class Controller : ControllerBase, <Omitted Interfaces>
{
     protected internal ViewResult View() {
            return View(null /* viewName */, null /* masterName */, null /* model */);
        }

     protected internal ContentResult Content(string content) {
            return Content(content, null /* contentType */);
        }

}
stackoverflowuser
  • 22,212
  • 29
  • 67
  • 92