Internal And Protected

I like to make sure that the members of the types (and the types themselves) that I define are only available to the types that need it. This is done by providing the appropriate scope. C# and VB.Net define 5 possible scopes – public, private, protected, internal (friend in VB) and internal protected (protected friend in VB). I’ll give a brief background on each so if you already know this stuff you can skip ahead:

Public

Public members are visible to all types whether they are defined in the same assembly or within another assembly. So given a class A, anyone that has an instance of A can call its Foo method.

public class A

{

   public void Foo() {}

}

Protected

Protected is sometimes referred to as Family in the CLR documentation. Basically protected means that only derived classes can access that member. So given a class A, only classes that derive from A can call its Foo method.

public class A

{

   protected void Foo() { }

}

Private

Private members are only available within that class. So given a class A, only class A can call its Foo method.

public class A

{

   private void Foo() { }

}

Assembly

Assembly scope is referred to as internal in C# and Friend in VB.Net. Assembly scoped members can be accessed by any type defined within the same assembly. So if you have assembly 1 with a class defined as follows, any other type defined within assembly 1 may access the Foo method but types defined in other assemblies cannot.

public class A

{

   internal void Foo() { }

}

Assembly Or Protected

Assembly Or Protected combines the scopes of Assembly and Protected. In C# this would be defined as internal protected and in VB.Net the member would be defined as Protected Friend. Members with this scope can be access by any type within the same assembly or types in other assemblies that derive from this type. So if you have assembly 1 with a class defined as follows, any other type defined within assembly 1 may access the Foo method and also any type that derives from A (including types defined in an assembly other than assembly 1) may access the Foo method.

public class A

{

   internal protected void Foo() { }

}

But there’s actually another scope – Assembly And Family. I used the terminology that’s used in the CLR documentation because it’s not available in C# or VB.Net. This scope is supposed to limit member access to only derived types within that assembly. Outside of that assembly or to non-derived types in the same assembly, it is as if that member doesn’t exist.

So if you have class A in assembly 1 that has a method named Foo with this scope, only classes within assembly 1 that derive from class A may access the Foo method. Personally I think this would be a useful scope to support. I even asked Jeffrey Richter at the PDC about the possibility of supporting it and he basically told me it wouldn’t happen and that I was the only person that had asked him that question. I was a little suprised by this. I spend a lot of time in reflector and there seem to be lots of cases where they could have used this type of functionality themselves.

Without this scope, you are forced to use internal instead and try to manage this via guidelines/standards. I can think of a couple of possible approaches that you could use to verify that this is the case – you could write an fxcop/static analysis rule that does the check or you could use reflection. The following method is a simple take on the latter. I’ll list the code first and then explain how it works.

    public static class Utilities

    {

        [MethodImpl(MethodImplOptions.NoInlining)]

        [Conditional("DEBUG")]

        public static void VerifyCallerIsFamily()

        {

            // get the method doing the check

            StackFrame sfCallee = new StackFrame(1, false);

            MethodBase calleeMethod = sfCallee.GetMethod();

 

            StackFrame sfCaller = new StackFrame(2, false);

            MethodBase callerMethod = sfCaller.GetMethod();

 

            Debug.Assert(calleeMethod.IsAssembly, “This method is meant to try and implement a scope of ‘Assembly And Family’ so the calling method should be internal.”);

 

            if (false == calleeMethod.DeclaringType.IsAssignableFrom(callerMethod.DeclaringType))

            {

                const string Format = “The ‘{0}.{1}’ method is being called from ‘{2}.{3}’. It should only be called by derived types.”;

                string message = string.Format(Format,

                    calleeMethod.DeclaringType.Name,

                    calleeMethod.Name,

                    callerMethod.DeclaringType.Name,

                    callerMethod.Name);

                throw new InvalidOperationException(message);

            }

        }

    }

The following will be our test scenario classes:

    public class Base

    {

        internal void OnlyCallFromDerivedClasses()

        {

            Utilities.VerifyCallerIsFamily();

 

            // do something

        }

    }

 

    public class Derived : Base

    {

        public void VerifyCanCallMethod()

        {

            this.OnlyCallFromDerivedClasses();

        }

    }

 

    public class NotDerived

    {

        public void VerifyCannotCallMethod()

        {

            Base b = new Base();

            b.OnlyCallFromDerivedClasses();

        }

    }

We could then test this out:

    Derived d = new Derived();

    d.VerifyCanCallMethod();

 

    NotDerived not = new NotDerived();

    not.VerifyCannotCallMethod();

The call to VerifyCanCallMethod on d will pass because Derived is a derived class and has the rights to make this call. The second call will result in an exception – “The ‘Base.OnlyCallFromDerivedClasses’ method is being called from ‘NotDerived.VerifyCannotCallMethod’. It should only be called by derived types.” – which is the behavior that we want.

Ok so how does this work. The majority of the code relies upon the use of the StackFrame class to obtain the information about the method requesting the verification (the callee) and the method that is calling that method (the caller). We have to pass in 1, since this is implemented as a helper method. Passing in 0 would return the VerifyCallerIsFamily method which we do not want.

Once we have the stackframes, we can get the MethodBase instances. These are reflection objects that provide information about the method being called. We can then use the IsAssignableFrom method to ensure that the caller is either the same type as the callee or a derived class. If it is not we raise an appropriate exception.

You may notice that I decorated the VerifyCallerIsFamily with 2 attributes. The MethodImpl attribute is used to ensure that the jitter will not inline the execution of the method. The method is a little large so its unlikely that it would but its best to make sure. We need to do this because we’re relying on getting the methods using specific indexes in the stack frame. The Conditional attribute is used to indicate that calls to this method should not be included unless the code is being compiled with the DEBUG compilation constant. In other words, we only want to do this check in a debug version. My main reason for doing this is that using a StackFrame has overhead and once we release our assembly, its really not necessary to do this check since the callee method is internal and our testing can be limited to checking calls within the same assembly.

I still hope they implement that scope in a future version of C# and VB.Net but until then this approach may help you to get close.

About these ads

40 Responses to “Internal And Protected”

  1. Karl Shifflett Says:

    Andrew,

    Deep, brother Deep!

    Your blog will quickly get a huge following.

    One problem. Mole forget to read your work and by-passes the scope attributes to display “hidden data”. :-)

    Best to you,

    Karl

  2. Internal And Protected Virtual « Andrew Smith Says:

    [...] Andrew Smith Random Thoughts about C#, VS, WinForms, WPF and .NET in General « Internal And Protected [...]

  3. Josh Smith Says:

    Holy smokes!! This is really amazing stuff. I agree with Karl, your blog is going to develop a cult-like following if you keep this up! :)

    Josh

  4. Alex Sarafian Says:

    Mr Smith recently I had the same problem. What I hadn’t realized was that intentionally protected internal scope allows class that inherit my class to use the protected internal member.

    I thought it was a bug. Now I realize that it is a not so good implementation in Object oriented approach. As i understand it a logic & applies to scopes.
    protected allows children class to access protected members of the father
    internal allows only class from the specific assebly to access specified members.

    So if you apply the & bitwise logic to protectd & internal, the natural conclution is what we both expected. That’s why i first thought of it as a bug.

    Personaly I believe that it is a huge problem, and being forced to used a solution like yours is not very appealing thought usefull if it comes to that.

    I should not be forced to use reflection nor by any means allow the consumer of my control understand that there are members that i have made tricks to protect from accessing.

    Thank you.

  5. agsmith Says:

    Hi Alex. Actually what you are describing – internal protected – is what the clr refers to as AssemblyOrFamily (or you might think of it as InternalOrProtected). This means that the member may be accessed by someone internally in the assembly OR by any derived class even one that is in another assembly. I described this in the blurb on scopes. The scope that is not supported currently is InternalAndProtected meaning that only members that are within that assembly AND derived from the class may access the member. I agree that we should not need to use reflection to do what the compiler should be handling for us. I merely offered the reflection approach as a way to try and enforce what is not currently supported.

  6. Alex Sarafian Says:

    I fully understood what you explained. I just thought from my expierence that two keywords interact with the AND logic, but from what you explained I was mistaken.

    Anyway thanks again for your answer.
    Nice solution though.

  7. Eric Says:

    Years later, unfortunately still no trace of internal AND protected keyword in .NET 4. IMHO, it would be much more useful than the current internal OR protected which forbid you to set a property as protected when using an internal type!
    Years of C# development behind, I wonder if I ever used “internal protected” once! (as I always though intuitively it would be AND instead of OR)

  8. www.cinemaallo.com Says:

    bonjour à tous,

    Ici Melisande
    Je suis une fille de trente et un années .
    je suis des études de agent de maintenance ! Est-ce un défaut
    d’être enjouée ?

  9. EMPORIO - ARMANI - EA7 - ARMANI JEANS - HUGO - BOSS » 72 Says:

    Je porte le joli nom de Azura.
    Je suis une jeune femme de 26 berges tant pis si ça ne se dit pas .

    Je suis une esthéticienne . Si je suis parfois une vraie prune,
    ce n’est pas forcément un défaut ?A

  10. Trisped Says:

    I ran into this problem while trying to make a property with a protected set in an internal class. No matter what accessor is placed on the property, if the set is protected and the class is internal then the following error is thrown:
    “The accessibility modifier of the ‘PropertyName.set’ accessor must be more restrictive than the property or indexer ‘PropertyName’”

    While I can see limited value for the protected OR internal (like if you are developing software libraries for resell), I also see a value for the protected AND internal. I just seems silly that the compiler does not automatically apply the internal access constraint to a protected item if its parent is internal. Sure, it might make it harder for library developers to know for sure that their property can be inherited, but if that was a big deal they could add a compiler argument to turn it on or off or add another keyword.

  11. Janette Says:

    I leave a response whenever I appreciate a post on a site or I have something to valuable to contribute to the discussion.
    Usually it’s triggered by the fire displayed in the article I read. And on this post Internal And Protected | Andrew Smith. I was excited enough to leave a thought ;) I do have a few questions for you if you don’t mind.
    Could it be simply me or do a few of the remarks appear as if they are
    written by brain dead folks? :-P And, if you are writing at
    other online social sites, I’d like to follow everything new you have to post. Would you list all of your community sites like your Facebook page, twitter feed, or linkedin profile?

  12. vacancestop.com Cuba » vacancestop.com Says:

    Je m’appelle Fabienne.
    Je suis une fille de quarante-huit printemps !
    Ce que je fais : barmaid . Mes amis disent régulièrement que je suis taciturne.

  13. sugar daddyHaigneville Says:

    Je suis une jeune de 44 ans .
    Je porte le joli nom de Eleanor.
    je suis des études de conductrice de ligne de fabrication .
    On dit de moi que je suis cool.

  14. Credit immobilier à Miami Says:

    bonjour Je m’appelle Fifine.
    Je suis vieille de quarante-trois ans .
    Je voudrais devenir scripte . Mon naturel est plutôt timide.

  15. rp-immoconseil.com Says:

    Really no matter if someone doesn’t be aware of afterward its up to other viewers that they will assist, so here it happens.

  16. 404 Not Found Says:

    salut,hello,ça roule ? Mon nom est Susanne.
    Je suis une femme de quarante-quatre printemps .
    Ce que je fais dans la vie, étudiante ! Si je suis parfois revêche, ce n’est pas forcément un défaut ?

  17. prix facette dentaire Says:

    Je m’appelle Cosette.
    Je suis agée de quarante-quatre années !
    Je suis agent de propreté urbaine . Il est dit parfois de moi que je suis drôle.

  18. http://kthkrynica.cba.pl/ Says:

    Je suis une jeune fille de 44 berges !
    Je porte le joli nom de Anne.
    Mon boulot, assistante maternelle ! Si je suis parfois
    joyeuse, ce n’est pas forcément un défaut ?

  19. occupedia.nl Says:

    hello, Je m’appelle Colette.
    Je suis agée de 30 années .
    J’ai repris mes études pour devenir éleveuse ! Mon caractère est plutôt réservé.

  20. georgio Armanie Says:

    Je suis une jeune fille de quarante-huit piges .
    Parnella à votre service
    Mon travail est fleuriste … Est-ce un défaut d’être attentionnée ?

  21. Lilla Says:

    We are a group of volunteers and starting a new
    scheme in our community. Your website offered us with valuable information to work on.
    You’ve done a formidable job and our entire community will be thankful to you.

  22. http://Nouvellelanguefrancaise.hautetfort.com Says:

    Hello; Je m’appelle Slainie.
    Je suis agée de quarante-six ans .
    Je suis graphiste . Mes amies racontent régulièrement que je suis pète sec.

  23. Dees Says:

    bonjour Je suis agée de trente-huit années ; je n’ai pas de problème là dessus .
    je suis Noémi
    je fais un stage de ingénieur chimiste . Mes amis disent que je suis un drole d’oiseau.

  24. Raymon Says:

    Good post. I learn something new and challenging on sites I
    stumbleupon every day. It will always be useful to read through content from other writers and practice a little something from their sites.

  25. billet d avion moin cher pour la tunisie Says:

    Ici Gabrielle
    J’ai trente-cinqA .
    je suis en ce moment des études de hôtesse de l’air .
    Mon caractère est plutôt timide.

  26. billet d avion cher Says:

    salut, J’ai trente-septA ; je n’ai pas de problème là dessus
    .
    Je me nomme Thérèse.
    je fais un stage de caviste . Il est dit de moi que je parais drôle.

  27. voyagerlibrary.com Says:

    hey ! je suis Yolette
    Je suis agée de 41 ans !
    je fais un stage pour devenir technicienne de labo .

    Est-ce un défaut que d’être enjouée ?

  28. Lin Says:

    bonjour à tous, je suis Avelaine
    Je suis agée de 40 années .
    je suis actuellement des études de enseignante .
    Si je suis parfois réservée, ce n’est pas forcément un défaut ?

  29. billet d avion le moin cher possible Says:

    Je viens de fêter mon 27ième anniversaire. !
    je suis Nicolette
    Mon boulot: urbaniste … il semble que je suis une vraie pomme.

  30. hotels Says:

    J’ai 41A !
    je suis Jacqueline
    J’ai repris mes études pour etre opératrice de fabrication !
    Je suis plutôt d’un naturel timide.

  31. office tourisme beaumont sur sarthe Says:

    Je suis vieille de trente-neuf printemps ,
    et j’assume totalement .
    Je me nomme Ermengardi.
    Mon travail est enquêtrice . Mes amis racontent que je suis rigolote.

  32. Un sejour pas cher en Republique Domincaine Says:

    bonjour Mon nom est Clementine.
    Je viens de fêter mon 34ième anniversaire. !
    J’ai repris mes études pour devenir prof de lycée . Est-ce un défaut que d’être enjouée ?

  33. Coque iphone 5 batterie Says:

    Mon nom est Luce.
    Je suis vieille de trente-six piges : je n’ai pas de complexe à le dire !
    je suis en ce moment des études de guide interprète . Je suis plutôt d’un caractère souriant.

  34. http://chmafa.com Says:

    Romaine à votre service
    Je souffle mes trente-neuf bougies dans un mois .
    je fais un stage de cartographe . Est-ce un défaut que d’être cool ?

  35. billet moins Cher tunisie Says:

    comment va ? Je suis vieille de quarante-trois berges !

    Capucine à votre service
    Ce que je fais : vendeuse en grande surface ! Est-ce
    un défaut d’être attentionnée ?

  36. http://xaueious.wordpress.com/ Says:

    J’ai 35A .
    Je porte le joli nom de Marjolaine.
    Mon occupation principale, prof de musique . il apparaît que je suis une bonne poire.

  37. Avis Destination Touristique Says:

    Je suis une jeune femme de 21 berges j’assume totalement mon age .
    Je me nomme Heloise.
    Mon métier, aide comptable . On dit régulièrement de moi que je suis pète sec.

  38. best clothes steamer Says:

    Hello everybody, here every person is sharing these knowledge, so it’s good to
    read this weblog, and I used to pay a visit this weblog everyday.

  39. best masticating juicer Says:

    This is the right website for anybody who hopes to understand this topic.

    You know a whole lot its almost tough to argue with you (not that I really will
    need to…HaHa). You definitely put a brand new spin on a
    subject which has been discussed for decades. Excellent stuff, just
    wonderful!

  40. best robotic pool cleaner Says:

    Thanks for sharing such a fastidious opinion, article is pleasant, thats why i have
    read it entirely

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: