8

FirstProcess と Second Process の 2 つのクラスがあります。

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);
        }
    }

以下のように計算メソッドを呼び出しました

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

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

出力

2 番目のプロセス X:1 および Y:2

2 番目のプロセス X:2 および Y:1

X=2 および Y =1 という予期しない結果が得られました。.Net はこのシナリオをどのように処理しますか? .net が名前付きパラメーターを優先するのはなぜですか?

4

2 に答える 2

10

メソッド呼び出しの引数バインディングはコンパイル時firstProcess.Calculate(x: 1, y: 2)に行われますが、メソッドは .xml であるため、メソッドのディスパッチは実行時に行われます。virtual

メソッド呼び出しをコンパイルするために、コンパイラはx: 1, y: 2、適切な IL を発行するために、この名前付き引数リストを参照して、順次インデックス付けされた引数リストに解決する必要があります (正しい順序でスタックに引数をプッシュしてから、メソッドを呼び出します)。

名前付き引数リストに加えて、コンパイラが利用できるもう 1 つの情報があります。それは、の静的型です。私もあなたも、実行時にこれがインスタンスになることを知っていますが、コンパイラーはそれを知りません (少なくとも一般的なケースでは)。そのため、 のパラメーター リストを調べて、それが最初の引数であり、2 番目の引数であることがわかります。これにより、あなたが書いたかのようにコードをコンパイルしますfirstProcessFirstProcessSecondProcessFirstProcess.Calculatexy

firstProcess.Calculate(1, 2);

実行時に、引数1と引数2がスタックにプッシュされ、仮想呼び出しが行われCalculateます。もちろん、これは を呼び出すことSecondProcess.Calculateになりますが、パラメーター名はランタイムへの移行を生き延びていません。は、最初の引数 ( ) および2 番目の引数 ( ) としてSecondProcess.Calculate受け入れ、観察された結果につながります。1y2x

余談ですが、これはデフォルトの引数値を使用した場合にも起こります。

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"

この話の教訓: 名前付き引数とデフォルト引数は便利ですが、それらが (必然的に) 実装される方法は、不愉快な驚きにさらされます。可能なときではなく、実際に具体的なメリットがある場合に使用してください。

于 2013-08-29T10:02:43.417 に答える
0

名前付きパラメーターを解決するとき、コンパイラーは動的タイプではなく、呼び出されるメソッドの静的タイプを使用します。

したがって、あなたの例でxは、最初のパラメーターとy2 番目のパラメーターを参照します。

于 2013-08-29T10:05:01.940 に答える