與時俱進,C# (CSharp) 跨平台之優勢篇


是的,C#已經可以跨平台了,而且還很好用,如果你還不知道,我就用開頭這一段講一下,已經知道的可以跳過哈。話說很久以前,C#是隨着.Net Framework一起出現的,而眾所周知.NET Framework又是Windows上的東西,所以好多人一聽到C#就想到Windows。其實.NET Framework是微軟用來對標Java的,所以他的設計比如虛擬機什么的理論上也是跨平台的,然后Linux有一幫人就覺得欸,這個.NET不錯額,就搞了個叫Mono的東西,在Linux下實現了.NET的虛擬機和API。說實話我那時候還沒用過C#,甚至看不慣微軟把Delphi的作者Anders Hejlsberg挖過去做C#(后來發現Borland自己也很不爭氣,現在還有人知道這個公司嗎😂),實在不懂這幫人為啥看上了Windows的.NET Framework,還花這么大功夫移植去Linux,感覺應該就像Wine、ReactOS那樣吃力不討好吧,覺得真的會有人用這種東西嗎。不過后來的后來,微軟自己也大力投入到開源軟件中,還把C#和.Net Framework也逐步開源化了,就有了現在本文主角.NET Core。簡單來說.NET Core是完全開源的、真正實現了他的前任.NET Framework未曾實現的跨平台,兼容絕大部分.NET Framework API的框架。實際上,隨着版本迭代,.NET Core的API已經比.NET Framework更豐富,.NET Core才是真正的未來,微軟已經不再向.NET Framework添加新功能了,新的功能都會放到.NET Core,未來兩個框架將會合並成一個.NET 5。

正文開始,首先列舉一下C#跨平台開發的優點,后面會展開講:

  1. 可以在Windows上開發、調試、性能調優,然后發布到Linux上運行,充分利用Windows的開發辦公效率和Linux的免費、高性能。Visual Studio大法好。在Linux上開發就算你Linux用得再熟,Office、郵件等排版都夠你頭痛的,IM工具普遍沒有Linux版。
  2. Windows現在有WSL,如果你喜歡Linux命令行,裝一個WSL跑起來比虛擬機快多了,文件和網絡也直接共享了,你還可以用VSCode直接在WSL環境調試.NET Core程序
  3. 如果你堅持要用Linux,那VSCode、C#插件、.NET Core這些全套都有Linux版,用起來一樣方便
  4. 可以用於Web服務器、應用服務器、客戶端、游戲等幾乎所有開發場景(應用服務器是本博客關注的重點,Web服務器已經很多有其他博主寫了)
  5. 支持異步編程,多項測評顯示,.NET Core執行性能與Go相當!內存占用一般是Go的兩倍左右,但C#開發效率比Go高。
  6. 如果你做服務器開發,異步模式比起多線程模式可以大大提高性能和吞吐量。
  7. 如果你做游戲、界面開發,耗時的IO操作、並行的動畫等使用async/await方式實現起來非常簡單,而且不用切換線程/Invoke,因為默認都跑在主線程中。
  8. 祖傳LINQ語法,寫算法非常方便,這一點比Go好很多,操作JSON、XML之類的也可以用哦
  9. 開源社區十分活躍(主要是國外,國內還沒跟上),迭代更新很快,開源庫很豐富,而且現在微軟除了.NET Core之外,還主導了相當多的開源項目,連Github都買下來了,開源這方面妥妥的。

有一說一,辦公Office、Visual Studio這些工具的效率、功能豐富性等還是別的平台很難趕得上的(估計很多人會反對,不過沒關系啦,用Mac和Linux也是可以的)。個人認為MacOS注重外表,實用性則為之讓步,而且稍微能用一點的軟件就要收費,用起來還常常沒Windows免費的好用。Linux折騰,軟件一天到晚變,很多時候沒周全考慮向前向后兼容性,你升級過幾次系統之后就知道這個折騰是什么意思了。我用過好多個系統之后,最終還是不想浪費生命,畢竟我也不年輕了,還想留多點頭發哈。然后Visual Studio絕對是你值得學習的IDE,調試的時候你甚至可以中途跳到指定的地方運行,簡直不要太方便,還可以分析內存泄漏、CPU占用瓶頸等,比起Linux下面gdb命令行一個一個線程翻,Visual Studio可以直接告訴你哪個函數占用CPU最多(不過異步下會有些讓人疑惑的地方,以后再另外寫一篇文章說)

國內C#主要是做Asp.NET(還經常捎帶SQL Server),還有就是做Windows界面了,另外Unity3D做游戲也是C#的一個強項。而自從有了.NET Core之后,顯而易見的是可以寫Linux服務器上的應用了。我自己已經用C#寫了一年多的跑在Linux下的量化交易程序、監控告警程序等,也是我第一次用C#作為主力開發語言,我發現C#寫算法真的不要太爽,LINQ語法太方便了,Lambda又簡潔,常常像 orders.Where(x => x.side == OrderSide.sell).Count()這樣一行代碼就完事,簡短又直觀易懂。我曾找過C++和Go版的類LINQ實現,結果發現這兩個語言的Lambda比較啰嗦,即使配合LINQ遠遠達不到C#的效果。這點也只有Python能打敗C#了,但是Python這種腳本語言缺乏靜態類型檢查,好多問題要到運行的時候才能發現寫錯了,浪費很多時間去調試,而且Python的異步開發還不太完善,從Python 3.6到3.7就還有挺大的變化,開源庫還要一段時間才能跟上來,如果不用異步開發的話,要不性能跟不上,要不得用多進程等更復雜的方式。

說到異步編程,就不能不提到Go了。Go是純異步的語言,在Go的語法和API里面,沒有線程,取而代之的是協程。Go的所有IO操作(比如網絡、文件等)都是異步的,這大大簡化了異步開發,你不需要擔心哪個IO操作會阻塞線程。相比之下,NodeJS的異步開發是比較原始的,采用回調的方式,當異步操作完成的時候,調用指定的回調函數,所以有一個笑話是一個JS代碼最后十幾頁都是“}”,因為回調函數層層嵌套😂。NodeJS這種稱為Proactor模式,還有更原始的Reractor模式,當可以開始某個IO操作的時候,系統通過回調函數通知你,這時候你再真正的發起一個IO請求,這種模式C/C++用的比較多,是Linux下的標准異步操作。目前C#的異步開發,采用的是async/await方式,比NodeJS的早期回調要先進一代,現在新的Javascript和Python都開始支持async/await語法了。前面說到Javascript經常出現的層層嵌套現象,其實從邏輯上來講,常常是順序執行的,比如我要先從A服務器請求一個數據,再到B服務器請求另外 一個數據,最后算出一個結果寫進數據庫,Javascrip就會嵌套3、4層回調,本來一個順序執行的代碼,結果縮進越來越多,代碼長的時候看起來特別費勁。如果不嵌套,拆成多個函數呢,那看起來就更累了,要跳來跳去地看,所以你就會看到以前很多異步的Javascript都是這樣層層嵌套的。而如果使用async/await方式,我們就可以把這種邏輯上順序執行的異步代碼,順序地寫下來即可:

async Task Process()
{
  var a = await RequestServerA();
  var b = await RequestServerB();
  var result = await ProcessAB(a, b);
  await SaveToDB(result);
}

看起來是不是比層層嵌套好很多。以后會詳細講這種async/await的代碼是怎么編譯怎么執行的,想看的記得繼續關注哦。由於C#不是純異步的語言,因此需要特別注意不要將異步和同步的IO調用混用,否則會阻塞線程,占滿線程池之后可能會卡死。從這點上來說,C#的異步是沒有Go方便的。但在C#中你可以更精准地控制線程,以及線程和協程之間的關系,有一個開源庫,Nito.AsyncEx,可以方便地做到這點,以后也會專門寫一篇說這個。通過Nito.AsyncEx,你還可以把所有的協程放到一個線程里執行,避免很多需要加鎖的場景,進一步簡化異步開發。其實C#本身需要加鎖的場景是不多的,因為所有對象都是引用,即使多線程操作,引用的讀寫是原子操作,寫不壞,但操作一些超過64位的struct就需要加鎖了,比如decimal,而我當時就是需要大量使用decimal,所以就用了一個單線程+異步的開發模式,免得到處加鎖。其實就算是一般的場景,我也不建議使用多線程,因為多線程只能縱向擴展,很難突破單機的天花板,而大數據時代,更需要的是橫向擴展,所以你更需要考慮的是多進程方式實現橫向擴展。

另外Go這個語言是有不少缺陷的,比如要通過字符串比較來判斷error是哪種錯誤,比如沒有函數重載,沒有缺省參數,沒有泛型,徒增很多重復代碼,特別是沒有泛型,你寫算法的時候就很難寫出可以重用的代碼和通用的庫,這是不可接受的,而且Go社區領導者的態度反而是要保持Go語言的簡潔,遲遲不願添加新功能,所以我不看好Go的生態,至少中短期內是這樣。實際上Go語言在國外是比較小眾並不很受歡迎的,而國內大企業鍾愛Go據說卻正是因為這個語言可以確保你寫不出花來,因為Go語法和編譯器檢查都很死板,諷刺啊。

說到開發效率,並不是簡單的看程序從無到有寫出來的時間而已,還要看代碼好不好維護,如果代碼只是寫出來快,但是無法重用,需要復制粘貼大量重復代碼,或者代碼表達能力差,比如語法特別啰嗦或者對格式限制太死,導致無法突出重點,又或者語法過於壓縮抽象,這些都不利於閱讀代碼,別人就會難以接手維護,甚至自己寫的代碼都看不懂。有人說好的代碼,代碼本身就是注釋,當然這個就比較理想化了,注釋還是要寫清楚的。

綜合來看,C#+.NET Core很優秀,開發效率和執行效率都很高,生態也比Go好,希望國內的環境能盡快跟上,不要一看C#就只想到Windows和過時了,這也是我開這個博客的初衷,我再也不想被迫用Go了😂。

好了,今天就先寫這么多,歡迎留言~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM