为了账号安全,请及时绑定邮箱和手机立即绑定

早期和晚期绑定

早期和晚期绑定

C#
慕虎7371278 2019-12-13 09:56:36
当C#中发生早期/晚期绑定时,我想尽我所能。非虚拟方法始终是早期约束。虚拟方法总是晚绑定的:编译器插入额外的代码来解析在执行时绑定到的实际方法,并检查类型安全性。因此,亚型多态性使用后期绑定。使用反射的调用方法是后期绑定的一个示例。我们编写代码来实现此目的,而不是编译器。(例如,调用COM组件。)关闭Option Strict时,VB.NET支持隐式后期绑定。将对象分配给声明为Object类型的变量时,它将被后期绑定。VB编译器在执行时插入代码以绑定到正确的方法并捕获无效的调用。C#不支持此功能。我朝着正确的方向前进吗?通过接口引用调用委托和调用方法呢?是早期绑定还是后期绑定?
查看完整描述

3 回答

?
森栏

TA贡献1810条经验 获得超5个赞

除非您通过Reflection接口,否则所有内容都在C#中早期绑定。

早期绑定只是意味着在编译时找到目标方法,并创建将调用此方法的代码。不管它是虚拟的(意味着在通话时还有一个额外的步骤来查找它都是无关紧要的)。如果该方法不存在,则编译器将无法编译代码。

后期绑定意味着在运行时查找目标方法。该方法的文本名称通常用于查找它。如果该方法不存在,请爆炸。该程序将在运行时崩溃或进入某些异常处理方案。

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

C#(版本4之前的版本)不会后期绑定;他们可以使用反射API来做到这一点。该API编译为通过在运行时挖掘程序集来查找函数名称的代码。如果关闭Option Strict,则VB可以后期绑定。

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


对于正常功能,编译器可以计算出它在内存中的数字位置。然后,当调用该函数时,它可以生成一条指令以在该地址处调用该函数。

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

因此,存在针对虚拟功能的查找。这是经过高度优化的,因此它将在运行时非常迅速地发生。

早起

  • 编译器可以计算出被调用函数在编译时的位置。

  • 编译器可以保证(在任何程序代码运行之前)该函数将存在并且可以在运行时调用。

  • 编译器保证函数采用正确数量的参数,并且参数类型正确。它还检查返回值的类型正确。

后期绑定

  • 查找将花费更长的时间,因为它不是简单的偏移量计算,通常需要进行文本比较。

  • 目标功能可能不存在。

  • 目标函数可能不接受传递给它的参数,并且可能具有错误类型的返回值。

  • 通过某些实现,目标方法实际上可以在运行时更改。因此,查找可以执行不同的功能。我认为这是在Ruby语言中发生的,您可以在程序运行时在对象上定义新方法。后期绑定允许函数调用开始调用方法的新替代,而不是调用现有的基本方法。


查看完整回答
反对 回复 2019-12-13
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

C#3使用早期绑定。

C#4使用dynamic关键字添加了后期绑定。有关详细信息,请参见Chris Burrow的博客条目。

对于虚拟方法还是非虚拟方法,这是一个不同的问题。如果我调用string.ToString(),则C#代码将绑定到虚拟object.ToString()方法。调用者的代码不会根据对象的类型而改变。而是通过函数指针表调用虚拟方法。对象的实例指的是指向对象表的ToString()方法。字符串的实例具有指向其ToString()方法的虚拟方法表。是的,这是多态性。但这不是后期绑定。


查看完整回答
反对 回复 2019-12-13
?
白衣染霜花

TA贡献1796条经验 获得超10个赞

早期绑定

该名称本身描述了编译器知道它是哪种对象,它包含的所有方法和属性。声明对象后,单击点按钮,.NET Intellisense将填充其方法和属性。

常见示例:

ComboBox cboItems;

ListBox lstItems; 在上面的示例中,如果我们键入cboItem并在其后放置一个点,它将自动填充组合框的所有方法,事件和属性,因为编译器已经知道它是组合框。

后期绑定

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

常见示例:

对象objItems;

objItems = CreateObject(“ DLL或程序集名称”); 在编译期间,这里没有确定objItems的类型。我们正在创建一个dll对象,并将其分配给objItems,因此一切都在运行时确定。

早期绑定与后期绑定

现在进入图片……

由于此处没有装箱或拆箱,因此应用程序在早期绑定中的运行速度将更快。

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

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

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

如果使用后期绑定,则代码对将来的增强的影响最小。

性能将是早期绑定中的代码。两者都有优点和缺点,这是开发人员根据情况选择合适的绑定的决定。


查看完整回答
反对 回复 2019-12-13
  • 3 回答
  • 0 关注
  • 380 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信