6

我正在测试在构造函数中调用虚拟成员的效果,并发现在调用该成员时产生的异常被包装在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!
        }
    }
4

2 回答 2

5

不,虚拟方法是通过virtual dispatch调用的。

这里没有使用反射。也不是任何虚拟方法调用。我相信异常的文档有点误导,因为这种类型异常是由通过反射调用的方法抛出的,但并非完全如此。

如果有人对为什么问题中的代码给出异常感到好奇,那是因为构造函数的执行顺序。构造函数与以下ClassB内容相同:

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

请注意对 的调用base(), this 在ClassB构造函数运行之前调用基本构造函数,因此在分配 _output 之前。虚方法在SplitTheWords基础构造函数中调用,解析为ClassB.SplitTheWords. 此方法尝试使用_output,因此出现错误。

要更详细地了解为什么不应该从构造函数调用虚拟方法,这个 SO question有一些有用的信息。Eric Lippert 也有一篇非常好的博客文章,说明为什么会出现这种情况。

于 2012-07-04T13:46:17.740 回答
0

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

不。

也不是来自构造函数,所以正在发生其他事情。查看调用您显示的代码的代码以及异常的堆栈跟踪将有所帮助。

于 2012-07-04T13:46:02.173 回答