.NET是“全部基于COM”吗?

34

多年来,我一直是Juval Lowy在.NET开发中教学和指导方面的崇拜者。他还写了我最喜欢的书之一:Programming .NET Components。

然而,在最近的DotNet Rocks播客(2010年1月)中,当谈论WCF/COM和.NET时,他发表了一些让我非常吃惊的评论:

Juval Löwy: ..... 在.NET中,每个类都是一个COM对象。我们知道这点。 实际上,它比COM更强大,因为我们有git编译,垃圾回收,安全性栈等等。

Carl Franklin: 嗯,你应该澄清一下。我的意思是,不是每个对象都是COM对象。每个对象具有COM对象的功能,但.NET Framework并不是一个COM库。

Juval Löwy: 不,不是这样的。首先,.NET实际上是建立在COM之上的。它下面全部都是COM。

然后,在Carl Franklin要求对此评论进行澄清之后:

Carl Franklin: 是的,我明白了。我的问题是.NET是建立在COM上的吗?

Juval Löwy: 当然,全部都是COM。

Carl Franklin: 不。我知道它们交织在一起并且是必需的,但当你创建一个.NET对象时,你并没有创建一个COM对象。

Juval Löwy: 你创建的是.NET对象,但我所说的是.NET是建立在COM之上的。.NET底层都是C++和COM。

Carl Franklin: 确实是C++,但你没有通过COM接口注册COM对象。不是所有那些东西。

Juval Löwy: 但是,有些东西在底层使用了COM,但这并不重要。忘掉它是如何制作的。

你怎么看待这些评论?

尽管我理解(并已确认)一些系统程序集是用非托管C++编写的,但也可以说它们全部都“在底层使用了COM”吗?

我原本认为完全有可能编写符合.NET CLI标准的C++程序集,并且与COM/ATL/ActiveX毫无关系?

这是有关该播客的PDF转录。请参阅第7页。


10
多么愚蠢的争论。他还不如说“.NET底层都是汇编语言实现的”。使用何种工具来实现.NET并不重要。当然,它的一部分是使用COM实现的,就像一部分是使用Win32调用实现的,还有一部分是用C++编写的。这完全不相关。 - jalf
2
@jalf,是的,我认为当Juval开始这个话题时,对于整个讨论来说并没有多大帮助。 - Ash
7个回答

20

我认为他谈论的是CLR的基础实现。据我理解,他并没有谈论COM和.NET世界的交互。他只是告诉我们他们在运行时实现中使用了C++和COM。

我曾以为可以编写符合.NET CLI标准的C ++程序集, 而这些程序集与COM / ATL / ActiveX 没有任何关系?

是的,你可以使用C++ / CLI创建纯MSIL程序集,与COM无关。


所以Juval的评论中真正不准确的是说“它全部都是COM”。应该是类似于“COM是.NET运行时的关键部分”。 - Ash
1
@Ash:确实。你可以构建一个与CLI兼容的运行时,而不用涉及COM。绝对不是所有的.NET对象都是COM对象。 - Mehrdad Afshari
我漏掉了一句非常重要的话,这导致了最大的混淆。Juval实际上说:“在.NET中,每个类都是一个COM对象。”我现在已经添加了它。 - Ash
@Ash:“每个类”是含糊不清的。他是在谈论托管类吗?如果是这样,我表示怀疑。如果他是在谈论用于编写CLR的类,那么这是可以理解的,但这与托管世界无关。这是一项实现细节。CLI规范绝对不要求运行时在COM之上实现。 - Mehrdad Afshari
播客的内容让我觉得他在谈论应用程序开发人员编写的托管类。Juval无疑是一个聪明的人,但在我看来,他有时会发表一些评论,似乎是特意设计的,以引起关注,甚至是事实上错误的。然后当被指出这些评论时,他会指出一个微妙之处(或边缘案例),以显示他在技术上是正确的。我认为这是一个典型的例子。当Carl Franklin要求他澄清他的评论时,我甚至还察觉到了一点后退。 - Ash

17

Dave Markle的回答让我想起了Jeff Richter在CLR Via C#中所说的话。

(第21章,CLR Hosting和AppDomains)

.NET Framework运行在Microsoft Windows之上。这意味着.NET Framework必须使用Windows可以与之接口的技术来构建。首先,所有托管模块和程序集文件都必须使用Windows可移植可执行文件(PE)文件格式,并且必须是Windows EXE文件或动态链接库(DLL)。

在开发CLR时,Microsoft将其实现为包含在DLL中的COM服务器;也就是说,Microsoft为CLR定义了一个标准的COM接口,并为该接口和COM服务器分配了GUID。当您安装.NET Framework时,代表CLR的COM服务器会像任何其他COM服务器一样在Windows注册表中注册。如果您想获取有关此主题的更多信息,请参阅随.NET Framework SDK一起提供的MSCorEE.h C++头文件。该头文件定义了GUID和非托管ICLRRuntimeHost接口定义。

我猜这已经很接近解释Juval的评论了。

Alex DeLarge在另一个答案中也提出了一个很好的观点,即CLR本身的实现和基础类库程序集之间存在区别。

我当时确实在关注BCL程序集(Juval:“这里的每个类都是COM对象”)和应用程序程序集,因此这可能是混淆的原因。


2
这很有趣。人们可以看出原始评论必须带着“一点点保留地”去理解。但是,所有的微软技术都是建立在其他技术之上的。这有点像一个分层蛋糕。或者垃圾场。;-) - Warren P

16
我相信Löwy特别是在谈论.NET的Windows实现。因为COM是Windows基础架构的重要组成部分,所以.NET使用它并不奇怪。然而,.NET也可用于非Windows平台,因此我不认为COM是.NET的基础。

4
关于 Mono 的看法很好。我想你可以说任何在 Windows 上运行的应用程序都是“基于 COM 的”。但是,这实际上只是在暗示 COM 仍然是 Windows 操作系统本身的一个关键部分。 - Ash
我漏掉了一个非常重要的引用,导致整个混淆。Juval实际上说:“在.NET中,每个类都是COM对象。”我现在已经添加了它。 - Ash
@Ash:即使如此也不是真的。除非至少有一个线程加载了OLE32.DLL并调用了CoInitialize(),否则进程不是COM进程。 - MSalters

7

Löwy的言辞似乎故意含混不清。我没有听过播客,但根据umlauts(音标符号)判断,他的母语不是英语。

在.NET中使用的一些对象确实是COM对象的包装器。您创建的.NET对象执行COM应该执行的许多操作以及更多操作,而没有COM的令人讨厌的麻烦。我认为“它全部都是基于COM”的说法不准确也不清晰。

我希望采访对象是Jeff Richter。


1
"Unclear" 还是 "nuclear"?我认为他是有意挑衅,还说所有的.NET对象都应该是WCF服务。英语绝对不是他的母语。在他的口音和路噪声之间,我发现很难在车里听。顺便说一句,他们也做了Jeff Richter的采访。 - Cylon Cat
@Dave,你真是了解我的想法 :) 我拥有一本优秀的《CLR Via C#》副本,但记不起Jeff Richter说过这样的话。 - Ash

6

.NET/CLR最初的目的是成为更好的COM(见本书第一章)。

但是.NET/CLR并不基于COM,因为它已经消除了COM的许多问题领域(如基于引用计数的内存管理、不安全指针、注册表依赖等)。

尽管如此,它仍然可以使用COM对象,并且可以将.NET对象包装在COM包装中。但是.NET对象并不是COM对象。

在Windows上,.NET实现的托管接口基于几个COM接口。


.NET没有哪些注册表依赖?就像DCOM/COM组件需要注册一样,您在注册表中也可以注册.NET包。 - Warren P
@Warren P:实际上,COM组件不一定需要注册。 - MSalters
2
@Warren P:COM组件应该放在HKEY_CLASSES_ROOT中以便使用(我知道有例外,比如隔离的COM等)。要使用.NET类,您不必在注册表中放置任何关于该类的内容。 - Arve

3

但是,与使用COM接口(和托管CLR)相比,CLR本身是否使用COM实现有很大的不同呢? - Ash

2

我听了他的讲话,我的印象是,虽然不是完全清楚,但他更多地谈论的是.NET运行时,而不是BCL。


我漏掉了一个非常重要的引用,导致整个混淆。 Juval实际上说“在.NET中,每个类都是COM对象”,现在我已经添加了它。 - Ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接