6

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!
        }
    }
m.edmondson
  • 30,382
  • 27
  • 123
  • 206

2 Answers2

5

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.

Community
  • 1
  • 1
Rich O'Kelly
  • 41,274
  • 9
  • 83
  • 114
  • 1
    +1 for "slightly misleading", that's an deeply confusing thing for the docs to say. One could write a console app that did nothing except `throw new TargetInvocationException();` - where would the reflection be then? – AakashM Jul 04 '12 at 13:55
  • I understand _why_ virtual members shouldn't be called from constructors, this is what prompted me to try this out – m.edmondson Jul 04 '12 at 14:04
  • @m.edmondson Apologies, I understood this from your line about 'I was testing the effects of...', I didn't intend for my answer to be condescending (but I think that it now may be), I merely included the last few paragraphs for completeness for others who see this answer. I'll try to rephrase. – Rich O'Kelly Jul 04 '12 at 14:08
  • No problems, it's better to provide a full answer – m.edmondson Jul 04 '12 at 14:22
0

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

NO.

Nor from a constructor, so something else is going on. It would help to see the code calling the code you have shown and the stack trace from the exception.

Richard
  • 106,783
  • 21
  • 203
  • 265