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

标签 c# .net

我有两个类 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 的意外结果。.Net 如何处理这种情况?为什么.net优先命名参数?

最佳答案

方法调用 firstProcess.Calculate(x: 1, y: 2) 的参数绑定(bind)在编译时完成,但方法分派(dispatch)完成运行时,因为该方法是虚拟的

为了编译方法调用,编译器看到 x: 1, y: 2 并且需要将这个命名参数列表解析为顺序索引的参数列表,以便发出适当的 IL (以正确的顺序将参数压入堆栈,然后调用方法)。

除了命名参数列表之外,还有一条信息可供编译器使用:firstProcessstatic 类型,即FirstProcess。现在我和你们都知道在运行时这将是一个 SecondProcess 实例,但编译器不知道(至少在一般情况下)。因此它查找 FirstProcess.Calculate 的参数列表,发现 x 是第一个参数,y 是第二个。这使得它编译您的代码就像您编写的一样

firstProcess.Calculate(1, 2);

运行时,参数12 被压入堆栈并进行虚拟调用以计算。当然,这最终会调用 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"

故事的寓意:命名参数和默认参数很方便,但它们(必然)实现的方式会让您感到不愉快。当它们提供真正有形的好处时使用它们,而不是在你可以的时候使用它们。

关于C# : overriding Method with optional parameters & named parameters : Unexpected Result,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18507785/

相关文章:

c# - 如何保证某些方法被定期调用?

c# - 如何在 UWP 的 NavigationViewMenuItems 中添加自定义图标

c# - 将 Keys 对象转换为枚举 Direction 对象?

c# - 如何使用 exe 文件附加资源(例如图像)?

c# - 具有包含 7 亿条记录的表的数据库

asp.net - 图像的 URL 重写

c# - 如何将属性信息发送回客户端代理?

c# - 在 MySQL 中存储文本和音频文件

c# - 如何在 asp.net mvc Controller 中获取发布的表单数据

c# - 如何使用匿名函数 (lambda) 复制此代码?