[英]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);
在運行時 ,參數1
和2
被推入堆棧,虛擬調用將進行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.