运行时类型与编译时类型方法调用 [英] runtime type vs compile-time type method invocation

查看:59
本文介绍了运行时类型与编译时类型方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#4.0规范如下:

The C# 4.0 specs read:

调用虚拟方法时,实例的运行时类型为调用发生的位置决定了实际的方法实现调用.在非虚拟方法调用中,实例的编译时类型是决定因素.

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.

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

At first, I thought this had something to do with initialization. For example, given two initializations:

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

和帮助程序类中的重载:

and an overload in a helper class:

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 期间,方法调用才会更改.

Method invokation is not impacted by the virtual keyword in this case. Regardless of having marked virtual, the least derived overload is called. Only during override in the Derived class does the method invocation change.

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

So, what do "runtime type" and "compile-time type" mean? How do they impact method invocation?

推荐答案

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

This is more a matter of virtual vs. non-virtual methods, and how the invocation occurs. The portion of the spec you are quoting deals with method calls on a variable - calling bcDerived.SomeMethod(), not calling foo.SomeMethod(bcDerived).

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

The specification you are quoting refers to the case where you have non-virtual methods:

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

然后,将在编译时由编译器确定 的方法,因此请执行以下操作:

Then the method called will be determined by the compiler, at compile time, so doing:

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

无论 someInst 引用A的哪个子类,都会导致它调用 A.Foo()是一种非虚拟方法.

Will cause this to call A.Foo(), no matter what subclass of A is being referred to by someInst, since this is a non-virtual method.

但是,如果有虚拟方法,则编译器会指定 callvirt 指令,该指令会将决策移至运行时.这意味着:

If you have a virtual method, however, the callvirt instruction is specified by the compiler, which moves the decision to runtime. This means that:

 someInst.Bar();

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

在您的情况下,您不是在调用虚拟方法(在规范所指的意义上),而是在进行标准方法解析.C#Spec的7.5.3详细处理了重载解析.在您的情况下,编译器会检查参数列表( bcDerived ),并将其定义为类型 BaseClass .最佳匹配"将是 public virtual void Method(BaseClass d),因为参数列表直接与参数列表匹配,因此可以在编译时使用.

In your case, you're not calling a virtual method (in the sense that the spec is referring to), but doing standard method resolution. 7.5.3 of the C# Spec deals with Overload resolution in detail. In your case, the argument list (bcDerived) is inspected by the compiler, and seen to be defined as type BaseClass. The "best match" for this is going to be public virtual void Method(BaseClass d) as the the parameter list directly matches the argument list, so that is used at compile time.

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

Method overload resolution, if you look at the specification, doesn't directly take virtual method calls into effect - it only looks at implicit conversions between types.

这篇关于运行时类型与编译时类型方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆