P.B*_*key 8 c# language-specifications
C#4.0规范如下:
调用虚方法时,进行该调用的实例的运行时类型决定了要调用的实际方法实现.在非虚方法调用中,实例的编译时类型是决定因素.
起初,我认为这与初始化有关.例如,给定两个初始化:
BaseClass bcDerived = new Derived(); VS 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");
}
Run Code Online (Sandbox Code Playgroud)
Methodvirtual在这种情况下,invokation不受关键字的影响.无论是否标记virtual,都会调用派生次数最少的重载.仅在overrideDerived类中,方法调用才会更改.
那么,"运行时类型"和"编译时类型"是什么意思呢?它们如何影响方法调用?
这更多的是虚拟方法与非虚方法,以及调用的发生方式.您引用的规范部分处理变量上的方法调用 - 调用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"); }
}
Run Code Online (Sandbox Code Playgroud)
然后调用的方法将由编译器在编译时确定,这样做:
A someInst = new B();
someInst.Foo();
Run Code Online (Sandbox Code Playgroud)
将导致此调用A.Foo(),不管是什么子类A的被提到了someInst,因为这是一个非虚方法.
但是,如果您有虚方法,则callvirt指令由编译器指定,编译器将决策移至运行时.这意味着:
someInst.Bar();
Run Code Online (Sandbox Code Playgroud)
会打电话B.Bar(),而不是A.Bar().
在您的情况下,您不是在调用虚拟方法(在规范所指的意义上),而是在进行标准方法解析.C#规范的7.5.3详细介绍了过载分辨率.在您的情况下,参数list(bcDerived)由编译器检查,并被视为定义为类型BaseClass.对此的"最佳匹配"将是public virtual void Method(BaseClass d)参数列表直接匹配参数列表,因此在编译时使用.
如果查看规范,方法重载解析不直接使虚方法调用生效 - 它只查看类型之间的隐式转换.
| 归档时间: |
|
| 查看次数: |
1723 次 |
| 最近记录: |