2012-07-04 2 views
6

Ich habe die Auswirkungen des Aufrufs eines virtuellen Members in einem Konstruktor getestet und festgestellt, dass beim Aufrufen dieses Members die resultierende Ausnahme in eine TargetInvocationException eingeschlossen wurde.Werden virtuelle Mitglieder über Reflektion (unter normalen Umständen) aufgerufen?

Nach dem docs dies:

Die Ausnahme, die durch Verfahren, durch Reflexion aufgerufen geworfen wird

Allerdings bin ich von irgendwelchen invokations durch Reflexion nicht bewusst. Also heißt das bedeuten virtuelle Mitglieder werden immer über Reflexion aufgerufen? Wenn nicht, warum ist es so in diesem Fall?

Der 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! 
     } 
    } 

Antwort

5

Nein, virtuelle Methoden werden über virtual dispatch aufgerufen.

Reflexion wird hier nicht verwendet. Und auch nicht für virtuelle Methodenaufrufe. Ich glaube, die Dokumentation für die Ausnahme ist leicht irreführend, da Ausnahmen dieses Typs durch Methoden ausgelöst werden, die über Reflektion aufgerufen werden, jedoch nicht ausschließlich.

Wenn jemand neugierig ist, warum der Code in der Frage eine Ausnahme gibt, liegt das an der Reihenfolge, in der die Konstruktoren ausgeführt werden. Der ClassB Konstruktor ist die gleiche wie:

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

Hinweis der Aufruf an base(), dies den Basiskonstruktor ruft, bevor der ClassB Konstruktor ausgeführt wird und somit vor _output wird zugeordnet. Die virtuelle Methode SplitTheWords wird im Basiskonstruktor aufgerufen, der in ClassB.SplitTheWords aufgelöst wird. Diese Methode versucht, _output zu verwenden, daher der Fehler.

Für eine detailliertere Betrachtung, warum virtuelle Methoden nicht von Konstruktoren aufgerufen werden sollten, enthält this SO question einige nützliche Informationen. Eric Lippert hat auch einen sehr guten Blog-Post darüber, warum das der Fall ist here.

+1

+1 für "leicht irreführend", das ist eine sehr verwirrende Sache für die Ärzte zu sagen. Man könnte eine Konsolen-App schreiben, die nichts außer "throw new TargetInvocationException();" - wo wäre die Reflektion dann? – AakashM

+0

Ich verstehe _why_ virtuelle Mitglieder sollten nicht von Konstruktoren aufgerufen werden, das ist, was mich dazu veranlasste, dies auszuprobieren –

+0

@ m.edmondson Entschuldigung, ich habe dies aus Ihrer Zeile über "Ich habe die Auswirkungen von ... getestet", ich Ich wollte nicht, dass meine Antwort herablassend ist (aber ich denke, dass es jetzt so sein mag), ich habe die letzten Absätze nur für die Vollständigkeit der anderen, die diese Antwort sehen, eingefügt. Ich werde versuchen, umzuformulieren. –

0

sind virtuelle Mitglieder über Reflexion (unter normalen Umständen) genannt?

NR.

Noch von einem Konstrukteur, so etwas anderes geht weiter. Es würde helfen, den Code zu sehen, der den Code, den Sie gezeigt haben, und die Stapelverfolgung von der Ausnahme aufruft.

Verwandte Themen