C# 语言特性系列(4) 深入理解虚方法
In a virtual method invocation, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke. In a non-virtual method invocation, the compile-time type of the instance is the determining factor. In precise terms, when a method named N
is invoked with an argument list A
on an instance with a compile-time type C
and a run-time type R
(where R
is either C
or a class derived from C
), the invocation is processed as follows:
- First, overload resolution is applied to
C
,N
, andA
, to select a specific methodM
from the set of methods declared in and inherited byC
. - Then, if
M
is a non-virtual method,M
is invoked. - Otherwise,
M
is a virtual method, and the most derived implementation ofM
with respect toR
is invoked.
For every virtual method declared in or inherited by a class, there exists a most derived implementation of the method with respect to that class. The most derived implementation of a virtual method M
with respect to a class R
is determined as follows:
- If
R
contains the introducingvirtual
declaration ofM
, then this is the most derived implementation ofM
. - Otherwise, if
R
contains anoverride
ofM
, then this is the most derived implementation ofM
. - Otherwise, the most derived implementation of
M
with respect toR
is the same as the most derived implementation ofM
with respect to the direct base class ofR
.
using System;
class A
{
public void F() { Console.WriteLine("A.F"); }
public virtual void G() { Console.WriteLine("A.G"); }
}
class B: A
{
new public void F() { Console.WriteLine("B.F"); }
public override void G() { Console.WriteLine("B.G"); }
}
class Test
{
static void Main() {
B b = new B();
A a = b;
a.F();
b.F();
a.G();
b.G();
}
}
A.F
B.F
B.G
B.G
Notice that the statement a.G()
invokes B.G
, not A.G
. This is because the run-time type of the instance (which is B
), not the compile-time type of the instance (which is A
), determines the actual method implementation to invoke.
using System;
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}
B.F
B.F
D.F
D.F
[我Case1]
2 {
3 public virtual void F() { Console.WriteLine("A.F"); }
4 }
5 class B : A
6 {
7 public override void F() { Console.WriteLine("B.F"); }
8 }
9 class C : B
10 {
11 public override void F() { Console.WriteLine("C.F"); }
12 }
13 class D : C
14 {
15 public override void F() { Console.WriteLine("D.F"); }
16 }
17 class Test
18 {
19 static void Main()
20 {
21 D d = new D();
22 A a = d;
23 B b = d;
24 C c = d;
25 a.F();
26 b.F();
27 c.F();
28 d.F();
29 }
30 }
Result: D.F
[我Case2]
2 {
3 public virtual void F() { Console.WriteLine("A.F"); }
4 }
5 class B : A
6 {
7 public override void F() { Console.WriteLine("B.F"); }
8 }
9 class C : B
10 {
11 //public override void F() { Console.WriteLine("C.F"); }
12 }
13 class D : C
14 {
15 //public override void F() { Console.WriteLine("D.F"); }
16 }
17 class Test
18 {
19 static void Main()
20 {
21 C c = new C();
22 A a = c;
23 B b = c;
24 //C c = d;
25 a.F();
26 b.F();
27 //c.F();
28 //d.F();
29
30 }
31 }
32
Result: ?
http://msdn.microsoft.com/en-us/library/aa645767(VS.71).aspx