最近在StackExchange的編程板塊上引發了一場關於「Mono是否能夠做爲跨平臺.NET」的討論。討論發起者提出了幾點「否認」見解,包括Mono建立者Miguel de Icaza在內的許多人給出了回覆。html
Thorbjorn在提問中認爲Mono並不能稱做是跨平臺的.NET,理由以下:程序員
用戶sparkie首先回應了以上幾點疑問:編程
首先,CLI(Common Language Infrastructure)和.NET是有區別的,前者是公開標準,然後者是微軟對這一標準的實現,Mono則是CLI的又一實現,它歷來不是「可移植的.NET」。一樣,C#也是一個公開標準,也不和.NET綁定在一塊兒。json
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了。app
所以,若是要考慮「.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支持:除WP七、CF、XBox、MonoTouch和PS3外的全部平臺 。
- CPU SIMD支持:Linux,、BSD、Solaris及MacOS X。即將支持PS 三、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:除WP七、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移植,不過他們的移植團隊沒有獲得反饋其成果的許可。