Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的动态调度模板方法#_C#_Dispatch - Fatal编程技术网

C# C语言中的动态调度模板方法#

C# C语言中的动态调度模板方法#,c#,dispatch,C#,Dispatch,我不明白为什么要打印以下输出 静态类型是Base,调用print()并导致控制台输出: 第1.A款 基地B 静态类型为Sub,调用print(),并导致控制台输出: 第1.A款 基地B 为什么这里叫Base.B而不是Sub.B 静态类型为Sub,对B()的调用导致控制台输出: 第1.B款 Sub上的隐藏函数B()在程序中被调用。但如果我用print()调用它,则不会 不同之处在于从每个位置调用每个方法的方式,归结起来就是new和virtual/override之间的差异 首先是理论,

我不明白为什么要打印以下输出

静态类型是Base,调用print()并导致控制台输出:

  • 第1.A款
  • 基地B
静态类型为Sub,调用print(),并导致控制台输出:

  • 第1.A款
  • 基地B
为什么这里叫Base.B而不是Sub.B

静态类型为Sub,对B()的调用导致控制台输出:

  • 第1.B款
Sub上的隐藏函数B()在程序中被调用。但如果我用print()调用它,则不会


不同之处在于从每个位置调用每个方法的方式,归结起来就是
new
virtual
/
override
之间的差异

首先是理论,对这两个关键词的解释过于简单:

  • new
    只是在派生类中定义了另一个方法,该方法与基类中的现有方法同名“隐藏”它。根据用于调用方法的引用类型,在编译时选择调用什么方法(base或derived)
  • virtual
    表示方法可以在派生类中具有替代实现,在这种情况下应该使用它。此处,根据实际对象的类型在运行时进行选择
现在把它应用到你的案例中。 这里对
A
的所有调用都完全相同,因为它是虚拟的,并且唯一的实例是
Sub
类型。动态分派完成了它的任务,这将导致调用
Sub.B
,正如您所发现的那样

但是对
B
的调用在两个地方。
print
方法中的一个和直接在
main
上的另一个。由于
B
不是
virtual
,它使用静态调度和编译时类型的引用来确定调用站点。来自
main
的一个很容易理解为什么它使用
Sub.B
。但是,
print
方法中的另一个方法不使用相同的引用,它们隐式地使用
this
指针调用同一类中的实例方法。这完全等同于这样写:

public void print()
{
    this.A();
    this.B();
}
因此,对
B
的调用完全取决于
this
的编译时类型,即本例中的
Base
(正如在该类中编写的那样)。因此这里调用了
Base.B


前面对
print
的调用来自另一种类型的变量,这一事实在这里是不相关的,因为这只用于确定要执行的
print
实现(这里我们只有一个),但是该方法本身所做的任何操作都超出了这一范围,因此不会影响其行为。

new关键字仅隐藏现有方法,而不会替换它。当您在基类中调用
print
时,基类不知道
Sub
上有另一个隐藏
B
的方法,它调用
B
它知道存在。但是使用virtual关键字它必须在虚拟调用表中查找Sub.A?然后,在运行时构造期间初始化该表?规范的10.6.3中有这样一句话:“在虚拟方法调用中,发生该调用的实例的运行时类型决定了要调用的实际方法实现”。我实际上不知道这背后的实现细节,但是规范中关于虚拟方法的部分(Visual Studio附带的版本中的10.6.3)似乎有很多您可能要查找的信息。根据这一点:在非虚拟方法调用中,实例的编译时类型是决定因素。感谢您对规范的提示:-)
public void print()
{
    this.A();
    this.B();
}