为什么.NET框架没有将类定义为一流类型的概念?


20

熟悉历史的人都知道,C#和.NET框架最初是由Delphi的首席开发人员Anders Hejlsberg设计的,“ Delphi被重写为Java感觉”。从那时起,事情发生了很大的分歧,但是在早期的相似性是如此明显,以至于甚至有人认真地猜测.NET实际上最初是Borland的产品。

但是最近我一直在看一些.NET东西,而Delphi最有趣,最有用的功能之一似乎完全消失了:类作为一流数据类型的概念。对于不熟悉它的人,类型TClass代表对类的引用,类似于Type.NET中的类型。但是,在.NET Type用于反射的地方,Delphi将其TClass用作语言的非常重要的内置部分。它允许各种有用的习惯用法,如果没有它,它们就不会存在,也不会存在,例如类子类型变量和虚拟类方法。

每种OO语言都有虚拟方法,其中不同的类以不同的方式实现方法的相同基本概念,然后根据运行时所调用对象实例的实际类型在运行时调用正确的方法。Delphi将此概念扩展到了类:如果您将TClass引用定义为特定的类子类型(即class of TMyClass,该变量可以接受继承自的任何类引用TMyClass,但不能继承继承体系中的任何内容),且该类引用附加了类范围虚拟方法通过使用类的实际类型,可以在没有实例的情况下调用它们。例如,将此模式应用于构造函数会使Factory实现变得很简单。

.NET中似乎没有任何等效的东西。与类引用一样有用(尤其是虚拟构造函数和其他虚拟类方法!),有没有人说过为什么将它们遗漏?

具体例子

形式反序列化

Delphi VCL DFM以DSL格式保存表格,以描述组件层次结构。表单阅读器解析DFM数据时,它跨如下所述的对象运行:

object Name: ClassName
   property = value
   property = value
   ...
   object SubObjectName: ClassName
      ...
   end
end

有趣的是这里的ClassName部分。每个组件类都会及时TClass在组件流式系统中注册initialization(请考虑静态构造函数,只有一点点不同,保证在启动时立即发生。)这会将每个类注册在string-> TClass哈希图中,且类名称为键。

每个组件都来自TComponent,它具有一个虚拟构造函数,该构造函数采用单个参数Owner: TComponent。任何组件都可以重写此构造函数以提供自己的初始化。当DFM阅读器读取类名称时,它会在上述哈希图中查找该名称并检索相应的类引用(如果不存在则引发异常),然后在其上调用虚拟TComponent构造函数,这被认为是很好的因为注册函数采用了从TComponent继承的类引用,所以您最终得到了正确类型的对象。

缺少这一点,WinForms等效项...坦白地说,这是一个很大的混乱,需要任何新的.NET语言来完全重新实现其自身的格式(反序列化)。当您考虑时,这有点令人震惊。因为拥有CLR的全部目的是让多种语言使用相同的基本基础结构,所以DFM风格的系统将具有完美的意义。

可扩展性

如果您尝试检索不在集合中但在数据源中可用的名称,那么我编写的图像管理器类可以提供数据源(例如图像文件的路径),然后自动加载新的图像对象。它具有一个类变量,该类变量的类型为class of基本图像类,表示要创建的任何新对象的类。它具有默认值,但是在出于特殊目的创建新图像时,有一些要点应以不同方式设置图像。(在没有Alpha通道的情况下创建它,从PNG文件中检索特殊的元数据以指定图片大小,等等。)

这可以通过编写大量的配置代码并将特殊选项传递给所有可能最终创建新对象的方法来完成...或者您可以仅使基本图像类的子类覆盖虚拟方法,已配置有关方面,然后根据需要使用try / finally块临时替换“默认类”属性,然后将其还原。使用类引用变量执行此操作要简单得多,而不是使用泛型即可完成。



3
您能否提供一个或两个具体的示例(其中a TClass有用)以及一些示例代码?在我关于的粗略互联网研究中TClass,我发现TClass可以作为参数传递。这是使用.Generics在.NET中完成的。工厂方法仅static在.NET中进行了标记,并且不需要类实例即可执行。
罗伯特·哈维

7
@RobertHarvey:对我个人而言,当我停止查看Java / C ++并重新将其视为具有对象的Modula-2时,C#开始变得更加有意义。Java也是如此:每个人都说它受C ++的影响,但事实并非如此。它的主要作用是Objective-C的(和Smalltalk经由)和Java将使很多更有意义,一旦你与类型,而不是C ++与GC把它当作Smalltalk的。
约尔格W¯¯米塔格

3
@RobertHarvey:TClass是一种基本语言功能,需要编译器支持。您不能不编写自己的语言而“自己编写”,对于.NET来说,这还不够,因为对象模型是由CLR而不是由单个语言定义的。从字面上看,这是.NET框架本身的一部分,否则它不存在。
梅森惠勒

4
首先,我可以肯定地说.NET最初不是“ Borland”产品。我怎么知道 我(还是现在)是开发Delphi的原始核心团队的一部分。我与Anders,Chuck,Gary和其他人紧密合作。当然,我确定您知道这一点。至于.NET中是否存在类引用(由于调用了TClass和类似的构造),由于存在丰富的运行时可访问类型信息,因此可能认为这是不必要的。Delphi开头的类型信息要少得多,而类引用是一种折衷方案。
艾伦·鲍尔

Answers:


5

.NET(CLR)是Microsoft的组件对象模型(COM)的第三代,在早期它被称为“ COM +运行时”。与Borland Delphi相比,Microsoft Visual Basic和COM / ActiveX控件市场对特定CLR体系结构兼容性选择的影响更大。(公认的事实是,Delphi已采用ActiveX控件确实有助于发展ActiveX生态系统,但COM / ActiveX在Delphi之前就已存在)

COM的体系结构是用C(不是C ++)设计的,并且专注于接口而不是类。此外,还支持对象组合,这意味着COM对象实际上可以由几个不同的对象组成,而IUnknown接口将它们链接在一起。但是IUnknown在COM对象创建中没有任何作用,该对象被设计为尽可能与语言无关。对象创建通常由IClassFactory处理,反射由ITypeLibrary和相关接口进行。关注点的分离与实现语言无关,并且每个核心COM接口的功能都保持最小且正交。

因此,由于COM和ActiveX控件的普及,建立了.NET体系结构以支持COM IUnknown,IClassFactory和ITypeLibrary。在COM中,这些接口不一定在同一对象上,因此将它们组合在一起不一定有意义。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.