C# 对以下方法的调用是否被视为后期绑定?

C# 对以下方法的调用是否被视为后期绑定?,c#,C#,1) 假设: •B1定义方法virtualM()和nonvirtualM(),其中前者是虚拟的,后者是非虚拟的 •B2源自B1 •B2覆盖virtualM() •B2在组件A •应用程序app没有对程序集a的引用 在下面的代码应用程序app中,动态加载程序集A,创建类型B2的实例,并调用方法virtualM()和nonvirtualM(): Assembly asemb=Assembly.Load(“A”); Type t= asemb.GetType(“B2”); B1 a = ( B1 )

1) 假设:

B1
定义方法
virtualM()
nonvirtualM()
,其中前者是虚拟的,后者是非虚拟的
B2
源自
B1

B2
覆盖
virtualM()

B2
在组件
A

•应用程序
app
没有对程序集a的引用

在下面的代码应用程序
app
中,动态加载程序集
A
,创建类型
B2
的实例,并调用方法
virtualM()
nonvirtualM()

Assembly asemb=Assembly.Load(“A”);
Type t= asemb.GetType(“B2”);
B1 a = ( B1 ) Activator.CreateInstance ( “t” );

a.virtualM();
a.nonvirtualM();
a) 调用
a.virtualM()
被认为是早期绑定还是后期绑定

b) 我假设对
a.nonvirtualM()
的调用在编译期间得到解决

2) 术语“后期绑定”是否仅指在运行时查找目标方法,还是指在运行时创建给定类型的实例

塔克斯


编辑:

(一)

--我假设对a.nonvirtualM()的调用在编译期间得到解决

  • 是的
如果我们有:

A a = new A();
a.M();
据我所知,在编译时不知道在运行时在堆上的哪个位置(因此在哪个内存地址)将创建实例
a
。 现在,通过早期绑定,在编译过程中,函数调用将替换为内存地址。但是,如果编译器不知道在运行时对象
a
将在堆上的何处创建(这里我假设方法
a.m
的地址也将与
a
位于相同的内存位置),那么它如何用内存地址替换函数调用呢

(二)

方法槽在编译时确定

我假设通过方法槽,您指的是V-table中的入口点?

1a)它是早期绑定

1b)是的。例如,如果将其更改为
a.nonexistentmethod()
,则会出现错误

2) 两者都是迟订的

a) 对a.virtualM()的调用被认为是早期绑定还是后期绑定

谁考虑的

方法槽在编译时确定。插槽的内容——实际调用的方法——在运行时确定

因此,绑定可以说是“晚了”

有人说,任何在编译时没有完全发生的绑定都是延迟绑定。有些人说,部分在编译时发生,部分在运行时发生的虚拟绑定仍然算作“早期”,其他人不同意。我想几乎所有人都同意,如果插槽直到运行时才确定,那么肯定是后期绑定

b) 我假设对a.nonvirtualM()的调用在编译期间得到解决

是的

2) 术语“后期绑定”是否仅指在运行时查找目标方法,还是指在运行时创建给定类型的实例

我从未听说过“后期绑定”指的是实例的创建

这里我假设方法a.m的地址也将与“a”位于相同的内存位置

这种假设是不正确的

如果你有

class C { internal int x; public int M() { return this.x; } }
然后,C的每个实例都不会在M中获得自己的代码副本。它们都共享M中代码的一个“副本”。您不会复制从未更改的内容;那将是对记忆的浪费。调用代码时:

C c = new C();
c.x = 123;
Console.WriteLine(c.M());
然后,c的托管地址被传递为“this”,控制权被转移到M的代码位置。该代码只有一个“副本”


运行时知道M的代码在哪里,因为运行时是JIT代码的地方,所以它知道它在内存中的位置。

Um,该代码不会像您预期的那样工作,特别是Activator.CreateInstance行我已经纠正了这个问题,thanxAspOnMyNet-有虚拟表(用于类)和虚拟表指针(用于类的实例),我认为您在“编辑1”问题中混合了这两个术语。PS:嗨,如果你有时间。。。为了回应你的回复,我编辑了我的第一篇文章。感谢大家的帮助,特别是伟大的bwana Eric Lippert先生