簡體   English   中英

C#:使用可選參數和命名參數覆蓋方法:意外結果

[英]C# : overriding Method with optional parameters & named parameters : Unexpected Result

我有兩個類FirstProcess和Second Process

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

產量

第二個過程X:1和Y:2

第二個過程X:2和Y:1

我得到了意想不到的結果,X = 2和Y = 1.How .Net處理這種情況? 為什么.net優先使用命名參數?

方法調用firstProcess.Calculate(x: 1, y: 2)參數綁定在編譯時完成,但方法調度在運行時完成因為該方法是virtual

為了編譯方法調用,編譯器看到x: 1, y: 2並且需要將此命名參數列表解析為順序索引的參數列表,以便發出適當的IL(按正確的順序推送堆棧上的參數) ,然后調用方法)。

除了命名參數列表之外,編譯器還有另外一條信息: firstProcess靜態類型,即FirstProcess 現在我和你們都知道在運行時這將是一個SecondProcess實例,但編譯器不知道(至少在一般情況下)。 因此,它查找FirstProcess.Calculate的參數列表,並看到x是第一個參數, y是第二個參數。 這使得它可以像編寫代碼一樣編譯代碼

firstProcess.Calculate(1, 2);

運行時 ,參數12被推入堆棧,虛擬調用將進行Calculate 當然,這最終會調用SecondProcess.Calculate ,但參數名稱在轉換到運行SecondProcess.Calculate仍未存活。 SecondProcess.Calculate接受1作為其第一個參數( y ),將2作為其第二個參數( x ),從而導致觀察到的結果。

順便說一句,這也是使用默認參數值時發生的情況:

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"

故事的寓意:命名和默認參數都很方便,但它們(必然)實現的方式讓你容易受到不愉快的驚喜。 當它們提供真正有形的好處時使用它們,而不是在可能的時候。

解析命名參數時,編譯器使用被調用方法的靜態類型,而不是動態類型。

因此,在您的示例中, x表示第一個參數, y表示第二個參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM