gpt4 book ai didi

c# - 运行时类型与编译时类型方法调用

转载 作者:太空狗 更新时间:2023-10-29 18:32:07 25 4
gpt4 key购买 nike

C# 4.0 规范如下:

When a virtual method is invoked, the runtime type of the instance for which that invocation takes place determines the actual method implementation to invoke. In a nonvirtual method invocation, the compile-time type of the instance is the determining factor.

起初,我认为这与初始化有关。例如,给定两个初始化:

BaseClass bcDerived = new Derived(); 对比 BaseClass bcBase = new BaseClass();

和辅助类中的重载:

public virtual void Method(Derived d)
{
Console.WriteLine("Result = derived called");
}

public virtual void Method(BaseClass d)
{
Console.WriteLine("Result = base called");
}
在这种情况下,

Method 调用不受 virtual 关键字的影响。无论是否标记了 virtual,都会调用最少派生的重载。只有在 Derived 类中的 override 期间,方法调用才会更改。

那么,“运行时类型”和“编译时类型”是什么意思?它们如何影响方法调用?

最佳答案

这更多是关于虚拟方法与非虚拟方法以及调用如何发生的问题。您引用的规范部分涉及对变量的方法调用 - 调用 bcDerived.SomeMethod(),而不是调用 foo.SomeMethod(bcDerived)

您引用的规范是指您拥有非虚拟方法的情况:

public class A
{
public void Foo() { Console.WriteLine("A.Foo"); }
public virtual void Bar() { Console.WriteLine("A.Bar"); }
}
public class B : A
{
public new void Foo() { Console.WriteLine("B.Foo"); }
public override void Bar() { Console.WriteLine("B.Bar"); }
}

那么调用的方法将在编译时由编译器决定,这样做:

A someInst = new B();
someInst.Foo();

将导致它调用 A.Foo()无论 someInst 引用 A 的哪个子类,因为这是一个非虚方法。

但是,如果您有一个虚拟方法,callvirt 指令由编译器指定,它将决定移至运行时。这意味着:

 someInst.Bar();

将调用 B.Bar(),而不是 A.Bar()

在您的情况下,您不是在调用虚拟方法(在规范所指的意义上),而是在执行标准方法解析。 C# 规范的 7.5.3 详细处理了重载解决方案。在您的情况下,参数列表 (bcDerived) 由编译器检查,并被视为定义为 BaseClass 类型。对此的“最佳匹配”将是 public virtual void Method(BaseClass d),因为参数列表直接匹配参数列表,因此在编译时使用。

如果您查看规范,方法重载解析不会直接使虚方法调用生效 - 它只会查看类型之间的隐式转换。

关于c# - 运行时类型与编译时类型方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14443202/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com