2013-08-29 25 views
7

Ich habe zwei Klassen FirstProcess und Zweiter ProzessC#: übergeordnete Methode mit optionalen Parameter & benannte Parameter: unerwartetes Ergebnis

public class FirstProcess 
    { 
     public virtual void Calculate(int x, int y) 
     { 
      Console.WriteLine("First Process X :{0} and Y{1}", x, y); 
     } 
    } 
    public class SecondProcess : FirstProcess 
    { 

     public override void Calculate(int y, int x) 
     { 
      Console.WriteLine("Second Process X :{0} and Y :{1}", x, y); 
     } 
    } 

I wie das calculate-Methode aufgerufen haben unter

var secondProcess = new SecondProcess(); 
      var firstProcess = (FirstProcess) secondProcess; 

      secondProcess.Calculate(x: 1, y: 2); 
      firstProcess.Calculate(x: 1, y: 2); 

Ausgabe

Zweites Verfahren X: 1 und Y: 2

Zweiter Prozess X: 2 und Y: 1

Ich habe ein unerwartetes Ergebnis, dass X = 2 und Y = 1. Wie. Net handhaben dieses Szenario? Warum .net Priorität benannten Parameter geben?

Antwort

9

Argument für den Methodenaufruf Bindung firstProcess.Calculate(x: 1, y: 2) wird bei der Kompilierung getan, aber Methode des Versand zur Laufzeit getan, weil die Methode virtual ist.

Um den Methodenaufruf kompilieren zu können, sieht der Compiler x: 1, y: 2 und muss diese benannte Argumentliste in eine sequenziell indizierte Argumentliste auflösen, um die entsprechende IL (die Argumente auf dem Stack in der richtigen Reihenfolge zu übertragen) Aufrufmethode).

Neben der genannten Argumente Liste gibt es eine weiteres Stück von Informationen zur Verfügung, die Compiler: die statischen Art von firstProcess, die FirstProcess ist. Jetzt wissen Sie beide, dass zur Laufzeit dies eine SecondProcess Instanz sein wird, aber der Compiler weiß das nicht (zumindest im allgemeinen Fall). So sieht es die Parameterliste von FirstProcess.Calculate nach und sieht, dass x das erste Argument ist, y ist das zweite. Dies macht es Ihren Code kompilieren, als ob Sie

firstProcess.Calculate(1, 2); 

Bei Laufzeit geschrieben hatte, die Argumente 1 und 2 auf den Stapel geschoben und ein virtueller Anruf wird an Calculate gemacht. Dies führt natürlich dazu, dass SecondProcess.Calculate aufgerufen wird, aber die Parameternamen haben den Übergang zur Laufzeit nicht überstanden. SecondProcess.Calculate akzeptiert 1 als erstes Argument (y) und 2 als zweites Argument (x), was zu dem beobachteten Ergebnis führt.

Als beiseite, dies auch ist, was passiert, wenn Sie Standardargument Werte verwenden:

public class FirstProcess 
{ 
    public virtual void Calculate(int x = 10) 
    { 
     Console.WriteLine("First Process X :{0}", x); 
    } 
} 

public class SecondProcess : FirstProcess 
{ 
    public override void Calculate(int x = 20) 
    { 
     Console.WriteLine("Second Process X :{0}", x); 
    } 
} 

var secondProcess = new SecondProcess(); 
var firstProcess = (FirstProcess) secondProcess; 

secondProcess.Calculate(); // "Second Process X: 20" 
firstProcess.Calculate(); // "Second Process X: 10" 

Die Moral der Geschichte: der Namen und Standardargumente sind bequem, aber die Art, wie sie sind (notwendigerweise) umgesetzt Blätter Sie öffnen sich für unangenehme Überraschungen. Verwenden Sie sie, wenn sie echte greifbare Vorteile bieten, nicht wann immer Sie können.

+0

+1 Ich habe gerade diesen Code durchgegangen, hat mich wirklich verwirrt. Danke für die Klarstellung. –

+0

ehrfürchtige Erklärung..dank viel jon – JEMI

0

Wenn benannte Parameter der Lösung, der Compiler die statischen Art des Verfahrens verwendet aufgerufen wird, nicht die dynamische Typ.

Daher bezieht sich in Ihrem Beispiel x auf den ersten Parameter und y auf den zweiten Parameter.

Verwandte Themen