早期和晚期的约束力

当C#中的早/晚绑定发生时,我试图让我的头脑发生变化。

非虚方法总是早绑定的。 虚拟方法总是迟到:编译器插入额外的代码来parsing在执行时绑定的实际方法,并检查types安全性。 所以亚型多态使用后期绑定。

使用reflection调用方法是后期绑定的一个例子。 我们编写代码来实现这一点,而不是编译器。 (例如调用COM组件。)

VB.NET在Option Strictclosures时支持隐式后期绑定。 当一个对象被赋值给一个被声明为Objecttypes的variables时,这个对象是延迟绑定的。 VB编译器插入代码以在执行时绑定到正确的方法,并捕获无效的调用。 C#不支持此function。

我正朝着正确的方向走吗?

那么调用委托并通过接口引用调用方法呢? 这是早期还是晚期的约束?

除非你通过Reflection接口,否则一切都早于C#。

早绑定意味着在编译时find目标方法,并创build将调用此方法的代码。 无论是虚拟还是不虚拟(意味着在通话时find它的额外步骤都是无关紧要的)。 如果方法不存在,编译器将无法编译代码。

后期限意味着在运行时查找目标方法。 通常使用方法的文本名称来查找它。 如果方法不在那里,砰的一声。 程序将在运行时崩溃或进入一些exception处理scheme。

大多数脚本语言使用后期绑定,并且编译语言使用早期绑定。

C#(版本4之前)不会延迟绑定; 他们可以使用reflectionAPI来做到这一点。 该API编译为通过在运行时search程序集来查找函数名称的代码。 如果Option Strictclosures,VB可以延迟绑定。

绑定通常会影响性能。 因为后期绑定需要在运行时查找,所以通常意味着方法调用比早期绑定的方法调用要慢。


对于正常的函数,编译器可以在内存中计算出它的数字位置。 然后当它被调用的时候,它可以产生一个指令来调用这个地址的函数。

对于具有任何虚拟方法的对象,编译器将生成一个v-表。 这本质上是一个包含虚拟方法地址的数组。 每个具有虚拟方法的对象都将包含由编译器生成的隐藏成员,即v-表的地址。 当一个虚拟函数被调用时,编译器会计算出v表中相应方法的位置。 然后,它将生成代码来查看对象v-table,并在此位置调​​用虚拟方法。

所以,有一个虚拟function发生查找。 这是非常优化的,所以它会在运行时很快发生。

早绑定

  • 编译器可以确定编译时调用函数的位置。
  • 编译器可以保证在程序运行之前(在任何程序运行之前)该函数将存在并且可以在运行时被调用。
  • 编译器保证函数采用正确数量的参数,并且它们是正确的types。 它还检查返回值的types是否正确。

后期绑定

  • 查找将花费更长的时间,因为它不是一个简单的偏移量计算,通常会进行文本比较。
  • 目标函数可能不存在。
  • 目标函数可能不接受传递给它的参数,并且可能具有错误types的返回值。
  • 通过一些实现,目标方法实际上可以在运行时改变。 所以,查找可能会执行一个不同的function。 我认为这发生在Ruby语言中,您可以在程序运行时在对象上定义一个新的方法。 后期绑定允许函数调用开始调用方法的新重写,而不是调用现有的基方法。

C#3使用早期绑定。

C#4使用dynamic关键字添加了后期绑定。 有关详细信息,请参阅Chris Burrow关于此主题的博客文章 。

至于虚拟方法和非虚拟方法,这是一个不同的问题。 如果我调用string.ToString() ,则C#代码绑定到虚拟object.ToString()方法。 调用者的代码不会根据对象的types进行更改。 而是通过一个函数指针表来调用虚拟方法。 对象的一个​​实例是指对象的表指向它的ToString()方法。 一个string的实例有虚拟方法表指向它的ToString()方法。 是的,这是多态。 但不是迟到的约束。

在大多数情况下,早期绑定是我们每天做的事情。 例如,如果我们在编译时有一个Employee类,那么我们只需创build该类的实例并调用任何实例成员。 这是早期的约束。

 //Early Binding **Employee** employeeObject = new **Employee**(); employeeObject.CalculateSalary(); 

另一方面,如果你在编译时没有这个类的知识,那么唯一的办法就是用reflection来延迟绑定。 我遇到了一个很好的video解释这些概念 – 这是链接 。

简单来说,早期绑定发生在编译时,编译器有关于types及其所有成员的知识,后期绑定发生在运行时,编译器不知道关于types和成员的任何信息。 我在YouTube上遇到了一个很好的video,解释了这些概念。

http://www.youtube.com/watch?v=s0eIgl5iqqQ&list=PLAC325451207E3105&index=55&feature=plpp_video

http://www.youtube.com/playlist?list=PLAC325451207E3105

这是一个非常古老的职位,但想增加更多的信息。 当你不想在编译时实例化对象时使用后期绑定。 在C#您使用Activator在运行时调用绑定对象。

早期绑定

该名称本身描述了编译器知道它是什么types的对象,它包含的所有方法和属性是什么。 只要你声明了这个对象,.NET Intellisense就会通过单击点button来填充它的方法和属性。

常见示例:

comboboxcboItems;

ListBox lstItems; 在上面的例子中,如果我们inputcboItem并放置一个点,它会自动填充combobox的所有方法,事件和属性,因为编译器已经知道它是一个combobox。

晚绑定

该名称本身描述了编译器不知道它是什么types的对象,它包含的所有方法和属性是什么。 您必须将其声明为对象,稍后需要获取对象的types以及存储在其中的方法。 一切都将在运行时间知道。

常见示例:

对象objItems;

objItems = CreateObject(“DLL或程序集名称”); 这里在编译期间,objItems的types不确定。 我们正在创build一个dll的对象,并将其分配给objItems,所以一切都在运行时确定。

早绑定与晚绑定

现在进入照片了

应用程序将在Early绑定中运行得更快,因为在这里没有装箱或拆箱。

更容易在早期绑定中编写代码,因为智能感知将自动填充

早期绑定中的最小错误,因为在编译时间本身检查语法。

后期绑定将支持所有types的版本,因为一切都在运行时决定。

如果使用了“延迟绑定”,则代码在将来增强function中的影响最小。

性能将在早期绑定代码。 两者都有优点和缺点,开发者决定根据场景select合适的绑定。

本文是构build.net组件的指南,在运行时使用Vb6项目中的后期绑定,附加事件并获得callback。

http://www.codeproject.com/KB/cs/csapivb6callback2.aspx

Interesting Posts