Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are virtual members called via reflection (in normal circumstances)?

I was testing the effects of calling a virtual member in a constructor, and discovered that when calling that member the resulting exception was wrapped within a TargetInvocationException.

According to the docs this is:

The exception that is thrown by methods invoked through reflection

However I'm unaware of any invokations via reflection. So does this mean virtual members are always called via reflection? If not why is it so in this case?

The code:

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

        public virtual void SplitTheWords()
        {
            //I've been overidden
        }
    }

class ClassB : ClassA
    {
        private readonly String _output;

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

        public override void SplitTheWords()
        {
            String[] something = _output.Split(new[]{' '}); //TargetInvocationException!
        }
    }
like image 612
m.edmondson Avatar asked Jul 04 '12 13:07

m.edmondson


1 Answers

No, virtual methods are called via virtual dispatch.

Reflection is not being used here. And nor is it for any virtual method calls. I believe the documentation for the exception is slightly misleading in that exceptions of this type are thrown by methods invoked via reflection, however not exclusively so.

If anyone is curious as to why the code in the question gives an exception, it is because of the order in which the constructors are executed. The ClassB constructor is the same as:

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

Note the call to base(), this calls the base constructor before the ClassB constructor is run and, hence, before _output is assigned. The SplitTheWords virtual method is called in the base constructor, which resolves to ClassB.SplitTheWords. This method attempts to use _output, hence the error.

For a more detailed look at why virtual methods should not be called from constructors this SO question has some useful information. Eric Lippert also has a very good blog post on why this is the case here.

like image 157
Rich O'Kelly Avatar answered Nov 01 '22 02:11

Rich O'Kelly