Can you protect your classes? Do you know your scoping rules?
Monday, November 09, 2009 9:02 PM
So! You think you know your scoping rules for C# eh? Check out this funky little nuance/difference between the CLR and C#! This surprised me, and it might surprise you too!
Have you ever created a class, decided to extend it with another one, then play with the access modifiers? Did you end up with a big mess of compiler errors? Why was that you might be asking yourself? I know I was, well, until I read Jeffrey Richter's CLR via C# book. SG recommended it to me and I'm glad he did. Here's one little tidbit of useful information that helped me from going bald (well..........faster than normal! haha )
Wait a sec, what are those "access modifiers" you ask? They're those public, protected, internal and private keywords you put on classes, methods, fields enums, etc. You probably (ie HOPEFULLY LOL) know what their differences are (if not, there are hyperlinks, check'em out on MSDN).
When you tried to play with your method declarations, did you find you were getting compile errors? Did you try having one method public in a base class, then try to hide it the inherited class? How did that work for ya? Did you have a protected method in the base class, only to try exposing it publically in the inherited class? Ya, full of compile errors eh? I think I can help explain a bit of what's going on.
The short answer is the scoping rules in C# have to be the same all the way down the object hierarchy. If it started out as a protected property, then it has to be a protected property all the way through to the end. If it's a public or private, then it is always a public or private!
That's the easy and short answer. Now for the "why?!"
If you look at the CLR, technically it lets you do exactly what you want. Well, as long as you're opening up the access modifiers. In other words, you can make a private method or property protected or public in the inherited class. Ya, you might have to reread that one again to make sure you got it right (I'm doing it right now actually haha). Yup, the idea is, TECHNICALLY the CLR will let you open up your methods, make them more open, to widen the access scoping rules. The kicker here is C# doesn't let you do it (read above).
hhhmmm "whatcha talk'n'bout Willis?"
It's the CLR which lets you widen the access to entities (your property, method, enum, etc) because to do otherwise would be a security risk. Imagine this, you have a class with a public property, say YourAddress, then you create another class which inherits from the first class but this time, you decide to make YourAddress property private. Let's say this is a WebService maybe or part of a Business Layer or EF, what ever. HHHMMMMMM If you were able to do this, imagine for a second, one of your jr developers (unknowingly of course) casting the inherited class to the base class, then doing a Console.WriteLine( YourAddress) to the XML output........hhhhmmmm so much for data protection there!!!!!!!!!!!!!!! That's why you can only "widen" your scoping rules but not narrow them.
Now, let's see this with a bit of code to help cement this concept. On the right is a class diagram of the sample code I've created so we/you/I can play with this a bit more. The meat of the code is below, very simplistic I know but it's only the access modifiers we're interested in.
public class BaseClass
//private methods can't be made virtual, so that test doesn't count,
//no sense putting those in there, can't extend'em
internal virtual string InternalMethod()
return "(interal InternalMethod) Go Habs Go!";
protected virtual string ProtectedMethod()
return "(protected InternalMethod) Go Habs Go!";
public virtual string PublicMethod()
return "(public InternalMethod) Go Habs Go!";
public class SubClass : BaseClass
internal override string InternalMethod()
return "(interal SubClass) Habs Rock!";
protected override string ProtectedMethod()
return "(protected SubClass) Habs Rock!";
public override string PublicMethod()
return "(public SubClass) Habs Rock!";
See how everything matches up, protected overrides protected, public......public, etc.
Now, let's try both "narrowing" and "widening" the access modifiers, they're both compile errors, so might as well do them both at the sametime. I made the public method protected (narrowing) and the protected method public (widening). The latter one is technicaly allowed by the CLR but now allowed in C#. Doesn't matter about "the technicalities" C# don't let you do that here either way.
The idea here is simple, design your classes from the ground up properly and don't rely on fancy tricks to hide/show properties with OOP/inheritence.
Now it's time to grab a coffee and get coding!
Source Code: http://www.pchenry.com:8080/svn/blog/trunk/2009/AccessModifiersTest