虚拟成员是通过反射调用的(在正常情况下)?

m.e*_*son 6 .net c# virtual exception access-modifiers

我正在测试在构造函数中调用虚拟成员的效果,并发现在调用该成员时,生成的异常被包装在一个TargetInvocationException.

根据文档,这是:

由反射调用的方法抛出的异常

但是我没有意识到通过反射的任何调用.那么这是否意味着虚拟成员总是通过反射来调用?如果没有,为什么在这种情况下呢?

代码:

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!
        }
    }
Run Code Online (Sandbox Code Playgroud)

Ric*_*lly 5

不,通过虚拟调度调用虚方法.

这里没有使用反思.并且它也不适用于任何虚拟方法调用.我相信异常的文档有点误导,因为通过反射调用的方法抛出了这种类型异常,但并非如此.

如果有人对为什么问题中的代码给出异常感到好奇,那是因为构造函数的执行顺序.该ClassB构造是一样的:

public ClassB() : base()
{
    _output = "Constructor has occured";
}
Run Code Online (Sandbox Code Playgroud)

注意调用base(),它在构造ClassB函数运行之前调用基本构造函数,因此在分配_output之前调用.该SplitTheWords虚拟方法被称为在基构造,其解析为ClassB.SplitTheWords.此方法尝试使用_output,因此错误.

为了更详细地了解为什么不应该从构造函数调用虚方法,这个SO问题有一些有用的信息.埃里克利珀也对为什么是这样的情况下,一个很好的博客文章在这里.