是的,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#跨平台开发的优点,后面会展开讲:
- 可以在Windows上开发、调试、性能调优,然后发布到Linux上运行,充分利用Windows的开发办公效率和Linux的免费、高性能。Visual Studio大法好。在Linux上开发就算你Linux用得再熟,Office、邮件等排版都够你头痛的,IM工具普遍没有Linux版。
- Windows现在有WSL,如果你喜欢Linux命令行,装一个WSL跑起来比虚拟机快多了,文件和网络也直接共享了,你还可以用VSCode直接在WSL环境调试.NET Core程序
- 如果你坚持要用Linux,那VSCode、C#插件、.NET Core这些全套都有Linux版,用起来一样方便
- 可以用于Web服务器、应用服务器、客户端、游戏等几乎所有开发场景(应用服务器是本博客关注的重点,Web服务器已经很多有其他博主写了)
- 支持异步编程,多项测评显示,.NET Core执行性能与Go相当!内存占用一般是Go的两倍左右,但C#开发效率比Go高。
- 如果你做服务器开发,异步模式比起多线程模式可以大大提高性能和吞吐量。
- 如果你做游戏、界面开发,耗时的IO操作、并行的动画等使用async/await方式实现起来非常简单,而且不用切换线程/Invoke,因为默认都跑在主线程中。
- 祖传LINQ语法,写算法非常方便,这一点比Go好很多,操作JSON、XML之类的也可以用哦
- 开源社区十分活跃(主要是国外,国内还没跟上),迭代更新很快,开源库很丰富,而且现在微软除了.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了??。
好了,今天就先写这么多,欢迎留言~