写点什么

讨论:“Mono 是个跨平台的.NET”是否是个正确的说法

  • 2010-11-30
  • 本文字数:4194 字

    阅读完需:约 14 分钟

最近在 StackExchange 的编程板块上引起了一场关于“Mono 是否可以作为跨平台.NET”的讨论。讨论发起者提出了几点“否定”看法,包括Mono 创建者 Miguel de Icaza 在内的许多人给出了回复。

Thorbjorn 在提问中认为 Mono 并不能称作是跨平台的.NET,理由如下:

  • OpenJDK 等 Java 提供商都通过了官方的 Sun TCK 来保证正常工作,Mono 似乎并没有通过 Microsoft TCK。
  • Mono 的发布总是落后于.NET,那么目前它又对.NET 支持到什么程度呢?
  • 如 WinForm 等 GUI 工具是否可以在 Mono 下正常工作?
  • 商业用户不会将开源框架作为备选方案。

用户 sparkie 首先回应了以上几点疑问:

首先,CLI(Common Language Infrastructure)和.NET 是有区别的,前者是公开标准,而后者是微软对这一标准的实现,Mono 则是 CLI 的又一实现,它从来不是“可移植的.NET”。同样,C#也是一个公开标准,也不和.NET 绑定在一起。

Mono 相对于.NET 是有些落后,但也只有一丁点而已。Mono 可以运行 C# 4.0 的代码(最新的.NET 版本),与此同时微软最近把所有的 DLR 代码都开源了(使用 Apache 2.0 授权协议),这意味着 mono 可以直接使用 IronPython,IronRuby,同时 F#也不久前也已经开源,再加上微软都会定期发布.NET 的 CTP 版本,因此 Mono 开发人员几乎可以时刻和.NET 保持同步。.NET 中的部分工具和扩展,如 Code Contract 等等,它们并没有 mono 中的完整实现,不过它们的使用并不广泛。如果这些扩展变得流行起来了,那么 Mono 也会提供对应的实现。

WinForm 没有得到完整的移植,因为它们是.NET 的特性功能,而并非 CLI 的一部分。CLI 中并没有定义特定的组件库。有一些组件库是跨平台的,例如 GTK#和 Silveright,如果你从编写应用程序的一开始就考虑到可移植性,那就不应该使用 WinForm/WPF。此外,Mono 提供了一个很薄的封装层,现有的 WinForm 应用程序可以可以比较容易地移植为 GTK#(不需要完全重写)。

Mono 提供了一个工具:Mono Migration Analyser(MoMA),它能检查一个.NET 应用程序能否移植到 Mono 上(如,是否使用了不可移植的类库,或是 P/Invoke)。

对于不愿意使用开源产品的商业应用,Mono 可以使用另一种授权方案,这时候 Mono 代码的归属权则交由 Novell 负责,此时授权方案便不是 LGPL 了。

因此,如果要考虑“.NET 可否移植”这个命题,我想如果你从一开始就考虑到框架的可移植性问题,则它是成立的。但如果换个说法“我有个使用.NET 开发的 Windows 应用程序,它应该可以在 Mono 上运行”,那就不正确了——不过 Mono 让移植这样的应用程序变得简单许多。

随后 Lloeki 谈论了他的工作方式:

除了技术方面的因素以外,关键还是在于编写代码的方式。

无论是哪种跨平台的应用程序(例如 Java,Python,Ruby……),如果在写代码时不考虑可移植性,那么你应该假设这些代码可以直接跨平台执行的可能性为零(即使实际上这样的可能性要高出许多)。你无法随便拿到一个程序集就保证它能在 Mono 下正确执行。

不过对于一个新项目(或是你可以轻易重构的项目),选择.NET/Mono 作为可移植的方案之一则是明智的,不过对于跨平台的代码来说,你还是需要不断地进行测试。如果你使用持续集成,那么只要简单的创建一个 Mono 构建的节点即可。只要养成良好的习惯(例如路径的分隔符),很多问题可以在开发阶段就解决掉,而绝大部分代码只要使用单元测试以及其他一些常见的实践方式,再加上一点点先期规划就能得到很好的跨平台性。剩下的,例如平台相关的代码(如 P/Invoke),则可以通过封装,为不同平台提供针对性的实现。这样产出的项目,几乎不会付出额外的代价就能得到很好的移植性。

当然,使用一个 Mono 中不存在或是不兼容的类库则另当别论,不过就我的个人而言还没有遇到这样的情况。这些是我们在工作中实际用到的做法,我可以放心的声称“.NET+Mono”是跨平台的解决方案。

对于 Mono 于.NET 功能的支持程度, Robert Michael 谈到:

我用过 Mono,我认为它就和其他开源平台一样好,只不过不是微软直接支持的而已。如果你能接受 Clojure 或 Scala 这样的开源项目,那么 Mono 也能让你满意。Mono 对于.NET 的支持程度可以参考 Mono Roadmap 页面。Mono 并不等同于.NET,它们有或多或少的区别,例如现在你还无法使用 Entity Framework。

Mono 不是.NET 的移植品,有些技术是 Mono 不会或不打算实现的(如 Workflow Foundation 或 WPF),此外它们还提供了微软.NET 外的其他一些技术,例如 SIMD 扩展。简单地说,Mono 和微软.NET 是基于相同基础——CIL 和 BCL——的两个不同项目。

在讨论中,Mono 创建者 Miguel de Icaza 给出了最为详细的回应:

“.NET 是否跨平台”是一个模糊的说法,无论是框架本身还是整体环境都在不断改变。

简单地说,作为.NET 的基础架构,CLI 标准是跨平台的,但如果要在不同平台上得到最好的体验,则势必要使用各自平台上有针对性的 API。CLI 技术家族从来没有试着要“一次编写,到处执行”,好比电话和大型机的区别实在是太大了。与其为不同平台提供统一的 API 和运行时,不如各自平台上的最佳体验提供最正确的工具。试想那些非 Windows PC 或 Unix 服务器的程序员,要知道如今已经出现了游戏设备,移动电话,机顶盒,分布式集群等太多激动人心的平台。

微软的.NET 框架不是跨平台的产品,它只能运行在 Windows 上。其他系统上还有一些.NET 框架的变体,例如 Windows Phone 7,XBox 360 和浏览器中的 Silverlight,它们都有些许不同的配置(Profile)。

如今你已经可以在各个主流的操作系统,电话,移动设备,嵌入式系统或是服务器上使用基于.NET 的技术,以下是各种 CLI 实现的列表,虽不完整,但应该可以覆盖 99% 的情况:

  • 基于 x86 和 x86-64 的计算机:
    • Windows:一般来说你会使用.NET 或 Silverlight,不过你也可以使用完整的 Mono。
    • Linux, BSD 或 Solaris:完整的 Mono 或 Silverlight。
    • MacOS X:完整的 Mono 或 Silverlight。
    • Android:Mono 及 Android 的子集。
  • ARM 计算机:
    • Windows Phone 7:Compact Framework 2010。
    • Windows 6.5 及更早:早期的 Compact Framework。
    • Android 设备:Mono/Android。
  • PowerPC 计算机:
    • 在 Linux,BSD 或 Unix 操作系统上使用完整的 Mono 功能。
    • 在嵌入式系统中使用 Mono,如 PS3,Wii。
    • 在 XBox36 上运行 Compact Framework。
  • S390, S390x, Itanium, SPARC 计算机:
    • 完整的 Mono 支持
  • 其他嵌入式操作系统:
    • .NET MicroFramework 或 Mono 的移动配置。

有时候相同的代码很难四处运行。例如 XNA 代码不会在每个桌面上运行,反之亦然。为了.NET 不同的配置里运行,你需要修改些许代码。以下是我所了解的一些配置:

  • .NET 4.0 配置
  • Silverlight 配置
  • Windows Phone 7 配置
  • XBox360 配置
  • Mono 核心配置:与.NET 配置相同,可以在 Linux,MacOS X,Solaris,Windows 和 BSD 里使用。
  • .NET Micro Framework
  • Mono 的 iPhone 配置
  • Mono 的 Android 配置
  • Mono 的 PS3 配置
  • Mono 的 Wii 配置
  • Moonlight 配置(与 Silverlight 兼容)
  • Moonlight 扩展配置(Silverlight 和完整的.NET 4 API)

以上配置都有多多少少的不同,这不是坏事。每个配置的设计都适应其平台,去除任何一个都是不明智的。例如,Silverlight API 可以控制浏览器,这不关电话什么事;由于缺少合适的支持,XNA 的着色功能对 PC 硬件也没有多少意义。你越早认识到.NET 不是个将开发人员绑定在特定硬件或平台上的解决方案,就能越早成为更好的开发人员。

这意味着,有些 API 或解决方案可以在多个平台中使用,例如 ASP.NET 可以用在 Windows,Linux,Solaris,MacOS X 上,因为.NET 和 Mono 都提供了这些 API。同时,ASP.NET 则无法在某些微软支持的平台上使用,例如 XBox 或 Windows 7,也不支持 Mono 的 Wii 和 iPhone 配置。

其他解决方案的本质也是一样的。要完整列出这些技术需要一张复杂的表格,我不知道如何在这里表现出来,不过这里有个特定技术与特定平台的列表:

核心运行时引擎(所有平台):

  • Reflection.Emit 支持:除 WP7、CF、XBox、MonoTouch 和 PS3 外的所有平台 。
  • CPU SIMD 支持:Linux,、BSD、Solaris 及 MacOS X。即将支持 PS 3、MonoTouch 和 MonoDroid。
  • Continuations - Mono.Tasklets:Linux、BSD、Solaris、MacOS、PS3 及 Wii。
  • 程序集卸载:只有 Windows。
  • VM 注入:Linux、BSD、MacOS X 及 Solaris。
  • DLR:Windows、Linux、MacOS X、Solaris 及 MonoDroid。
  • 泛型:在 iPhone 和 PS3 上存在一些限制。

语言:

  • C# 4:所有平台。
  • C# 编译器即服务:Linux、MacOS、Solaris、BSD 及 Android。
  • F#、IronRuby 及 IronPython:除 WP7、CF、Xbox、MonoTouch 及 PS3 外的所有平台。

服务器技术:

  • ASP.NET:Windows、Linux、MacOS、BSD 及 Solaris。
  • ADO.NET:所有平台
  • LINQ to SQL:所有平台
  • Entity Framework:仅 Windows
  • XML 核心技术:所有平台
    • XML 序列化:除 WP7,CF 和 XBox 外的所有平台。
  • LINQ to XML:所有平台
  • System.Json:Silverlight,Linux,MacOS,MonoTouch,MonoDroid(译注:可移植到其他平台
  • System.Messaging:Windows、Linux、MacOS 和 Solaris 的支持则需要 RabbitMQ。
  • .NET 1 Enterprise Services:仅 Windows。
  • WCF:完整版仅支持 Windows。Silverlight、Solaris、MacOS、Linux、MonoTouch、MonoDroid 支持其自己。
  • Windows Workflow:仅 Windows。
  • Cardspace identity:仅 Windows。

GUI 技术:

  • Silverlight:Windows、Mac 和 Linux(Moonlight)
  • WPF:仅 Windows
  • Gtk#:Windows、Mac、Linux 及 BSD
  • Windows.Forms:Windows、Mac、Linux 和 BSD
  • MonoMac - 原生 Mac 集成:仅 Mac
  • MonoTouch - 原生 iPhone 集成:仅 iPhone/iPad
  • MonoDroid - 原生 Android 集成:仅 Android
  • Media Center API:仅 Windows
  • Clutter:Windows 和 Linux

图像类库:

  • GDI+:Windows、Linux、BSD 及 MacOS
  • Quartz:MacOS X、iPhone 及 iPad
  • Cairo:Windows、Linux、BSD、MacOS、iPhone、iPad、MacOS X、PS3 及 Wii

Mono 类库 - 跨平台,可以在.NET 里使用,不过需要手动编译:

  • C# 4 编辑器及服务
  • Cecil - CIL 操作,工作流,CIL 探测,链接器
  • RelaxNG 类库
  • Mono.Data.* 数据提供者
  • 完整的 System.Xaml(用于安装程序,.NET 没有提供这个技术)

MonoTouch 为 iPhone 上运行的 Mono,MonoDroid 为 Andriod 上运行的 Mono。PS3 和 Wii 的移植只供索尼和任天堂认证的开发人员使用。

在讨论中 Miguel de Icaza 还表示,IBM 至少完成了两个针对 AIX 的 Mono 移植,不过他们的移植团队没有得到反馈其成果的许可。

2010-11-30 04:147121
用户头像

发布了 157 篇内容, 共 55.6 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

4个实验,彻底搞懂TCP连接的断开

捉虫大师

TCP

初级Java面试题大全,极客邦科技面试,linux架构学习视频

Java 程序员 后端

别再说你不会!linux服务器搭建教程视频百度网盘,nginx入门书籍

Java 程序员 后端

十年Java编程开发生涯,尚学堂网易上的中级,推荐一个GitHub项目

Java 程序员 后端

Tapdata 携手精诚瑞宝,共拓 Real Time DaaS 蓝海市场

tapdata

数据库

分享Java资深架构师的成长之路,今日头条面试经历

Java 程序员 后端

分享我在Java开发中走的一些弯路,不同层级的Java开发者的不同行为

Java 程序员 后端

助你面试一臂之力,linux基础教程第2版课后思考题答案,阿里巴巴Java面试题

Java 程序员 后端

厉害了!尚硅谷mysql中employees表,腾讯T2手把手教你

Java 程序员 后端

劲爆!java微信小程序开发教程视频,Java学习路线指南

Java 程序员 后端

华为Java面试题及答案,java开发实例教程课后答案石磊,查漏补缺

Java 程序员 后端

鸿蒙轻内核源码分析:异常钩子模块系统中断异常,如何转储异常信息

华为云开发者联盟

鸿蒙 内存 存储 函数 异常钩子

十分钟带你回顾Spring常问的知识点,springcloud面试题汇集与答案

Java 程序员 后端

十分钟带你看懂Netty如何实现C-S,美团Java开发面试

Java 程序员 后端

厉害了!java使用教程视频,我的Java春季历程

Java 程序员 后端

DoS?DDoS?这件事要从另一个D说起……

郑州埃文科技

网络安全 DOS攻击 IP定位

分享一点面试小经验,2021年互联网大厂Java笔经

Java 程序员 后端

分享复习经验和后台开发面经,阿里架构师深入讲解Java开发

Java 程序员 后端

别再说自己不会JVM虚拟机了,35岁技术人如何转型做管理

Java 程序员 后端

Android 构建工具--AAPT2源码解析(一)

vivo互联网技术

打包APK 源码剖析 Android端

声纹识别帮你守住钱袋子,聊一聊证券行业里的人工智能

Zilliz

AI 向量检索 Milvus 向量

华为财经2021春招面试,尚硅谷springboot笔记,最全Java知识总结

Java 程序员 后端

卧薪尝胆70天内推入职阿里,2021Java春招

Java 程序员 后端

区块链交易隐私如何保证?华为零知识证明技术实战解析

华为云开发者联盟

区块链 金融 零知识证明 同态加密 交易隐私

分享一波阿里、字节、腾讯、美团等精选大厂面试题,Java面试题整理

Java 程序员 后端

分享一点面试小经验,2021吊打面试官系列

Java 程序员 后端

华为大神花费5个月打造的这份714页学习笔记系列,面试看这个就够了

Java 程序员 后端

分享一次面试经历,享学课堂java架构师课程,【高级Java架构师系统学习】

Java 程序员 后端

云栖大会:《永不止步的云上创新》——蒋江伟

代码 科技革命 计算 云 原生云 CTO 云栖大会

别再说自己不会了!极客时间破解版没用,Redis成神之路电子版教程已问世

Java 程序员 后端

十年Java编程开发生涯,未来教育计算机二级java激活码,面试官突击一问

Java 程序员 后端

讨论:“Mono是个跨平台的.NET”是否是个正确的说法_.NET_赵劼_InfoQ精选文章