The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Archive for the 'C#' Category

Is There A Good Reason To Hide Inherited Members?

Posted by Davy Brion on 17th January 2010

A mistake that i used to see a lot, and sometimes still do, is that developers hide inherited members in derived types.  For those of you who don’t know what that means, check out the following class:

    public class MyClass

    {

        public void DoSomething()

        {

            Console.WriteLine("i’m doing something important");

        }

    }

 

As you can see, the DoSomething method does something important, so you as a developer should consider its behavior important as well.   In some cases, you might want to add something extra to this behavior in a derived class.  Some developers would do that like this:

    public class MyDerivedClass : MyClass

    {

        public void DoSomething()

        {

            base.DoSomething();

            Console.WriteLine("(i’m just better at it)");

        }

    }

 

When they compile this, they’ll get the following warning:

warning CS0108: ‘HidingMethods.MyDerivedClass.DoSomething()’ hides inherited member ‘HidingMethods.MyClass.DoSomething()’. Use the new keyword if hiding was intended.

When this occurs, either one of 4 things can happen:

  1. The developer doesn’t bother to read compiler warnings (an offense worthy of a bitchslap) and is not aware of a possible problem
  2. The developer sees the warning and just adds the ‘new’ keyword to the method.
  3. The developer reads the documentation to figure what this really means, and hopefully realizes his mistake.  If he does, he combines this option with option 4.  If he doesn’t, he goes the option 2 route.
  4. The developer realizes his mistake and either makes the base method virtual and adds the override keyword to the method in the derived class, or when that’s not possible, either renames the method or thinks of a different approach.

If you’re unlucky, you either end up with no modification or the method will now look like this:

        new public void DoSomething()

        {

            base.DoSomething();

            Console.WriteLine("(i’m just better at it)");

        }

 

Great, no more compiler warning! All is well in the world now, right?

Err… not really.

The DoSomething method of MyDerivedClass actually hides the original DoSomething method. 

The following code will always produce the expected behavior:

            new MyClass().DoSomething();

            new MyDerivedClass().DoSomething();

 

That is, when the DoSomething method of an instance of MyClass is called, it will obviously execute the original DoSomething method.  And if the DoSomething method of an instance of MyDerivedClass class is called through a reference of MyDerivedClass then it will call the ‘new’ DoSomething method.

The following code however, would not produce the expected behavior:

        static void DoIt(MyClass subject)

        {

            subject.DoSomething();

        }

 

        static void Main(string[] args)

        {

            DoIt(new MyClass());   

            DoIt(new MyDerivedClass());

 

            Console.ReadLine();

        }

 

In this example, the DoSomething method is always called through a reference of MyClass.  When the DoIt method receives an instance of MyClass, the original DoSomething method will obviously be executed.  What some (many?) people unfortunately aren’t aware of is that when an instance of MyDerivedClass is passed into the DoIt method, the ‘new’ DoSomething method will not be executed but only the original one will be executed.  The reason is because methods that hide inherited members can only be called through references of the type, or derived types of that, that hides the inherited method.  Doesn’t really sound like a fun situation to debug, right?

So anyways, back to my original question: is there any valid reason why you would want to do this? Or better yet, can you share a situation where you had to resort to hiding an inherited member and if so, are you happy with the solution or did you consider it a hack?  And are you aware that it is essentially a bug waiting to happen?

So far, i have never actually seen a valid reason for doing this.  The only reason i’ve seen so far for occurrences of hidden members was because the developers that used it simply didn’t know any better.  In some cases, either me or someone else wasted debugging time on this when a piece of code that used a reference of a base class suddenly didn’t do what was expected when it was passed an instance of a derived class which hid the original method.  

I have read of only one valid reason to do this, and that is if a (either virtual or non-virtual) method with the same signature is introduced outside of your control in a base class that you can’t modify (like say, a class in the .NET framework or some other 3rd party assembly that you depend on) and you want to get rid of the compiler error that you got when recompiling against the newer version of the assembly.  In that case, it does make sense though i’d still say it’s going to be a future source of confusion sooner or later, and quite likely lead to a future bug as well.  In that situation, i’d much rather rename the member in my class.  Even if it means that consumers of my code will be forced to deal with the breaking change.  After all, a simple rename will always be less work than having to debug an issue because of a hidden member.

Posted in C# | 19 Comments »

Checking Whether A Method Is Overridden

Posted by Davy Brion on 11th January 2010

One of the requirements for using Agatha’s Caching Layer is that your request types must override the Equals and the GetHashCode methods.  In order to limit the number of questions i’m going to receive about the caching layer not working correctly the amount of time people will waste on debugging when they don’t override these methods, i wanted to add a check to the initialization of Agatha which makes sure that each cacheable request type indeed overrides Equals and GetHashCode.

I actually had to think about how i could do this, but it turned out to be very simple.  The trick is basically to retrieve the MethodInfo of the method you’re interested in, and then check the declaring type of that method.  If the method has been overridden, the declaring type will equal the type of the class you’re checking.  If it hasn’t been overridden, the declaring type will be that of one of the base classes:

        private static bool CheckIfOverrideExists(Type type, string methodName)

        {

            var methodInfo = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);

 

            if (methodInfo == null)

            {

                return false;

            }

 

            return methodInfo.DeclaringType == type;

        }

 

Not sure if there’s a better way to do this (if so, please share) but for now, this is good enough for me.

Posted in C# | 12 Comments »

Virtual Method Performance Penalty

Posted by Davy Brion on 10th January 2010

You often hear/read that one of the reasons why C# methods aren’t virtual by default is because of performance.  Calling a virtual method is more expensive than calling a regular instance method, because the CLR has to determine the correct override to call at runtime, instead of being able to simply call the instance method directly.  Another reason why virtual methods are more expensive to call is because they can never be inlined.

Is it really that much more expensive though? I ran a little experiment and i’d like to share the results with you.

Suppose you have the following 2 classes:

    public class MyClass

    {

        protected long someLong;

 

        public void IncreaseLong()

        {

            someLong++;

        }

 

        public virtual void VirtualIncreaseLong()

        {

            someLong++;

        }

    }

 

    public class MyDerivedClass : MyClass

    {

        public override void VirtualIncreaseLong()

        {

            someLong += 2;

        }

    }

 

As you can see, there is no difference between the IncreaseLong and VirtualIncreaseLong methods, except that the latter is virtual and the former is a regular instance method.  According to many people, calling VirtualIncreaseLong instead of IncreaseLong will be more expensive.  I also have a derived class which overrides the VirtualIncreaseLong method with a slightly different implementation.

If we call these methods a bunch of times (like 1000000000 times), we should notice quite a difference according to many people.

I wrote the following test code which calls these methods a bunch of times, times it, and outputs the results.

    class Program

    {

        const int numberOfTimes = 1000000000;

 

        static void Main(string[] args)

        {

            var myObject = new MyClass();

            var myDerivedObject = new MyDerivedClass();

 

            // we do this so there’s no first-time performance cost while timing

            EnsureThatEverythingHasBeenJitted(myObject);

            EnsureThatEverythingHasBeenJitted(myDerivedObject);

 

            TestNormalIncreaseMethod(myObject);

            TestVirtualIncreaseMethod(myObject);

 

            TestNormalIncreaseMethod(myDerivedObject);

            TestVirtualIncreaseMethod(myDerivedObject);

 

            Console.ReadLine();

        }

 

        static void EnsureThatEverythingHasBeenJitted(MyClass theObject)

        {

            theObject.IncreaseLong();

            theObject.VirtualIncreaseLong();

        }

 

        static void TestNormalIncreaseMethod(MyClass theObject)

        {

            Console.WriteLine(string.Format("calling the IncreaseLong method of type {0} {1} times", theObject.GetType().Name, numberOfTimes));

 

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < numberOfTimes; i++)

            {

                theObject.IncreaseLong();

            }

            stopwatch.Stop();

 

            Console.WriteLine("Elapsed milliseconds: " + stopwatch.ElapsedMilliseconds);

        }

 

        static void TestVirtualIncreaseMethod(MyClass theObject)

        {

            Console.WriteLine(string.Format("calling the VirtualIncreaseLong method of type {0} {1} times", theObject.GetType().Name, numberOfTimes));

 

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < numberOfTimes; i++)

            {

                theObject.VirtualIncreaseLong();

            }

            stopwatch.Stop();

 

            Console.WriteLine("Elapsed milliseconds: " + stopwatch.ElapsedMilliseconds);

        }

    }

 

The output of running this code might surprise you.  On my machine, i got the following results when the code was compiled in debug mode:

manual_compile_debug

The difference between calling the regular instance method and the virtual method is quite small.  I’d even say it’s negligible.

When compiling in release mode, i got the following output:

manual_compile_optimized

I ran the test a bunch of times, and there was no consistent observable performance penalty when calling the virtual methods.  In fact, the virtual methods often performed faster than the regular instance methods and in most cases were equally fast.  I’m not claiming that virtual methods are faster than regular instance methods, but if there really was an extra real-world performance cost associated with virtual methods, it surely should be observable with this test code, no?

Obviously, this test isn’t scientific in any way.  But still, i think it does show that the so called performance cost associated with virtual methods is highly overrated.  There definitely will be cases where virtual methods are more expensive than regular instance methods, but i’m willing to bet that those cases are rare and that the vast majority of .NET developers will never be negatively impacted by it. 

Side note: have you ever noticed that most people who recommend to avoid virtual methods due to their performance cost never put the same emphasis on avoiding the cost of say, frequent remote operations?  Which is odd, since i wouldn’t be surprised if that would be the most common reason for performance problems with .NET applications.  Then again, that’s what you get when the biggest company pushing a platform advocates meaningless performance improvements while at the same time pushing bad architectural decisions/guidelines on the world because the resulting code is supposedly easier to write, use and maintain.

You can download the example code here so you can run the test yourself. 

Posted in C#, Performance | 18 Comments »