Click here to Skip to main content
15,892,965 members
Articles / Programming Languages / C#

Virtual Method Call In contructor

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
30 Jul 2014CPOL2 min read 20.6K   6   4
I recently discovered the following warning from ReSharper: So what exactly does Virtual member call in constructor actually mean, and why am I being warned about this?Virtual membersIn C# a virtual member is a method or property which is prepended with the modifier virtual, meaning that it may

This article appears in the Third Party Products and Tools section. Articles in this section are for the members only and must not be used to promote or advertise products in any way, shape or form. Please report any spam or advertising.

I recently discovered the following warning from ReSharper:

So what exactly does Virtual member call in constructor actually mean, and why am I being warned about this?

Virtual members

In C# a virtual member is a method or property which is prepended with the modifier virtual, meaning that it may be overridden in a child class but unlike the abstract modifier it doesn't have to be. Since a virtual member may be overridden many times, only the most derived type will be executed.

Constructors

Since only the most derived virtual member is executed this can lead to a unique problem in the scenario where the virtual member is contained within a constructor. To understand this consider the following two classes:

C#
class ClassA
    {
        public ClassA()
        {
            SplitTheWords();
        }

        public virtual void SplitTheWords()
        {
            //I've been overridden
        }
    }
C#
class ClassB : ClassA
    {
        private readonly String _output;

        public ClassB()
        {
            _output = "Constructor has occured";
        }

        public override void SplitTheWords()
        {
            String[] something = _output.Split(new[]{' '}); //Bang!
        }
    }

If I create an instance of ClassB, then the constructor of ClassA will be called and SplitTheWords() will be executed. Now because SplitTheWords() is virtual, then only SplitTheWords() in ClassB will actually be executed (the most derived class) before the constructor of ClassB has been. Which means we could be using an object in an unsuitable state.

Resharper recommends to make the virtual member in ClassA sealed, which means that it cannot be overridden and must be the most derived type, which entirely solves this problem.

I believe this is exactly the kind of thing which would get overlooked in your codebase, and just goes to show what a useful tool ReSharper actually is. A more concise explanation of this situation is available in the ReSharper docs.

Note about comments below:

Due to a typo I made, an earlier version of the post didn't exhibit the behaviour described, and I very much thank those who took the time to point this out to me. This have now been fixed, although I believe a deeper explanation as to the reasons behind this article is warranted:

[10.11] of the C# Specification tells us that object constructors run in order from the base class first, to the most inherited class last. Whereas [10.6.3] of the specification tells us that it is the most derived implementation of a virtual member (in this case ClassB) which is executed at run-time.

Therefore when you call a virtual member in a constructor the following can happen because the most derived implementation of a virtual member was contained within an object whose constructor hadn't been executed yet:

This article was originally posted at http://www.matthewedmondson.info

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United Kingdom United Kingdom
Selected articles are published on codeproject. For all of my content, including how to contact me please visit my blog.

Comments and Discussions

 
SuggestionTwo hmmmms Pin
alex2001_ts1-Aug-14 3:12
professionalalex2001_ts1-Aug-14 3:12 
> Resharper recommends to make the virtual member in ClassA sealed
Hmmm...

I followed the link you provide and found nothing of the sort.

Ilya Ryzhenkov's comment is "Such virtual method, in fact, should be pure function that returns some value and doesn't depend on the state of derived type. If this is the case, make such function static (since it is pure) and pass its return value to base type as parameter to protected constructor."

Nothing about "sealed".

> make the virtual member in ClassA sealed, which means that it cannot be overridden
> and must be the most derived type, which entirely solves this problem.
Hmmm...

a) an attempt to declare ClassA.SplitTheWords sealed causes compilation error "CS0238: 'VCIC.ClassA.SplitTheWords()' cannot be sealed because it is not an override";

b) an attempt to declare ClassB.SplitTheWords sealed passes the build w/o errors but the problem is not solved, the call to Split causes the same "Object reference not set to an instance of an object." exception as before.

It looks like the solution is a bit more complicated, see

http://stackoverflow.com/questions/17991419/solving-the-virtual-method-call-in-constructor-issue

Anyway, thank you for reminding about the issue, can be quite a trap...

A pro po, as pointed out by Duncan Worthy in

http://blog.duncanworthy.me/swdev/csdotnet/constructor-gotchas-part1/

C++ behaves differently!

Regards
GeneralRe: Two hmmmms Pin
Matthew Edmondson1-Aug-14 22:52
Matthew Edmondson1-Aug-14 22:52 
QuestionVisual Studio warning CA2214 Pin
Bernhard Hiller1-Aug-14 2:24
Bernhard Hiller1-Aug-14 2:24 
AnswerRe: Visual Studio warning CA2214 Pin
susad2-Dec-15 4:04
susad2-Dec-15 4:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.