C# 对以下方法的调用是否被视为后期绑定?
1) 假设: •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 )
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先生