はじめに
最近、長年Webで連れ添ったPHPを捨て(たい[希望])、そしてもう、新しい言語を覚えるのが苦痛になってきた年齢になってきたので、C#言語だけでお願いしますという心境になってきた今日この頃。学習もかねて、今後Qiitaでは、C#言語についての話題をメインに書いていこうと思い、この言語の紹介を自分なりにしてみることにしました。
C#言語とは
C#言語は、MicrosoftにやってきたDelphiというWindowsにとって最強のGUIの開発環境を作り上げてきた方(アンダース・ヘルスバーグ氏)により作成されたプログラム言語です。C言語系統の構文を採用しており、Delphi(ObjectPascal言語)からいくつか言語機能を拝借し、そしてJava言語に近い構文等の仕組みを持っています。C#言語そのものは、.NET(dotnet)と親密な関係にあり、ほぼdotnetのフレームワーク基板を利用してプログラミングをしていくことになります。
言語の仕様・環境自体がオープンソース化され、いろんな言語の影響を受けたり与えたりして発展しています。言語の破壊的仕様変更(バージョンによって言語の構文が使えなくなったり意味が変わってしまったりすること)は、出来る限り行われないようにしているようですが、最近の8.0のバージョンにて、流行の取り入れにより、比較的大きく影響のある言語仕様の変更が行われました。
.NET(dotnet)とは
元は、Microsoft .NET Framework という総称であった、共通言語基板(CLI)上に成り立つフレームワークになります。現在は、.NET Core を基板とした環境に移り、次の.NETから .NET5 という名称として、Microsoft .NET Frameworkと.NET Core が統合されることになりました。
.NET自体は、環境の総称であり、Javaのプラットフォームと同様のものですが、Javaと違う点は開発に利用できる言語が特定されないということになります。C言語やC++言語であってもJava言語であっても開発できますし、PythonやPHP、Ruby等の動的型付け言語からでも.NET向けのプログラミングが可能になっています。
現在の.NETは、オールマイティーなプラットフォーム環境であり、Windows/Mac/Linux向けのGUI/CUIを問わないアプリ開発から、iOS/Androidのモバイル向けのアプリ、Unityを使ったゲーム開発、ASP.NET Core/Blazorを利用したWebアプリ、AIの開発まで、他のプログラム言語や環境とは違い、出来ないことがほとんどないという状況になりつつあります。
以前ならば、この分野はJavaが唯一の利点であったのですが、Oracleに取り込まれ、そして有償化、訴訟問題などと問題を事欠かないこととなりました。一応、オープンソースで公開されている部分もあり、無償で使うことも可能ですが、サポート期限が短いなどという問題など、方向性の固定化にはもう少し時間かかりそうです。そうしている間に、利用者がいなくなりそうです。
ちなみに、「C#言語でできること」と書いていますが、どちらかというと.NETという環境が、色々できるということになります。あくまでC#は、言語であって、実行されるときはC#言語の形は残ってません。C#言語をコンパイルすると、中間言語または各種機械語(Intel互換CPU:x86,AMD64互換CPU:x64,ARM互換CPU:ARM etc)のバイナリコードになります。一応.NETのメインプログラム言語がC#言語とされているため、C#言語でできることにしました。なお、.NETはJava環境と違って、言語は特に限定されていません。C++言語で、VBでもF#言語でも、そのほか、PythonでもPHPでもプログラミングできたりします。
ネイティブとインタプリタ【実行形態】
「ネイティブ」とは、この業界では「機械語(Intel互換(x86)/AMD64互換(x64)/ARM/PowerPCなどのCPUが直接識別できる)」のことを示し、ネイティブコンパイルというと、各種言語のソースコードを機械語に翻訳し、直接CPUにて実行できるコードに変換されることを示します。
ですが最近、「ネイティブ」という言葉は、中間言語バイナリを示す場合もあります。一例としては、WebAssembly があります。ブラウザ上では、通常Javascriptでプログラミングしますが、Javascript はスクリプト言語であるため、どうしても実行速度で劣る部分があります。そこで、WebAssembly を使って実行することで、処理速度が向上するという謳い文句ですが、実質、配布される環境は中間言語に変換されたバイナリになります。ウェブで実行する環境の特性上、実行する環境は、ユーザーによって異なるの(PCだとx86/x64系,スマホやゲーム機だとARMなどが多い)ので、機械語にしての配布は不可能ですので、実質ネイティブではないということになります。
今まで提供されていたC#言語と.NETでは、コンパイルすると中間言語(MSIL)に変換され、実行時に、中間言語をその環境の機械語に変換してから実行を開始するというJITコンパイル方式(実行時コンパイル)を採用していました。
中間言語方式では、必ず実行環境上で、実行時にネイティブに変換してコードを実行させるか(JITコンパイル)、中間言語を解釈できるインタプリタに解釈させて実行させる方式のいずれかになります。
また、PHPやJavascriptとは違って、中間言語方式は、構文解析や意味解析を行い、チェックが完了(コンパイルエラーがなければ)したら、構文自体を機械語に比較的近いバイナリコードに変換し、実際実行するプログラムが、処理を解析・実行しやすい構造になっているため、PHPやJavascript等のスクリプト系に比べて、処理速度が比較的早くなりますが、あらかじめネイティブとして出力されている実行形態と比べ、実行時に、JITコンパイルで中間言語をネイティブに変換、それから実行という流れになるため、起動の時間差によりネイティブとの実行の差はでてしまいますし、JITコンパイルによるコンパイル時間が長いと本来動かしたいコードが起動するまでにかなりの時間がかかる点は残されていること、そして一般的な事前コンパイルして出力されるネイティブコードと違い、コードの最適化を行う時間の余裕がないために、最適化を施したC言語等でコンパイルした純粋な機械語のコードよりは遅くなるという点はあります(他にも遅くなる要因はいくつもありますが)。
しかし、あらかじめネイティブに変換するよりも中間言語を通して実環境でコンパイルして実行する方が効率がいい場合があります。それは、実行時に利用環境のCPUの情報を得て、機械語を出力できるということです。ご存知の通りPCにおいてもモバイル端末においても、毎年、新しいCPUが登場しています。クロック数やコア数が増えたりする以外にも、内部的に処理できる命令が増えていたりするわけです。中間言語のインタプリタやJITコンパイルを更新すれば、これら新しい命令を取り入れて実行させることができ、そのため中間言語方式の方がネイティブよりも効率の良い実行ができる可能性がありえます。
さて、現在のC#言語は中間言語以外も出力できます。各種機械語(つまりネイティブのコード)を出力することができます。正確には、今までもJITコンパイルにより、各種環境の機械語を出力していたのですが、AOT(aHead of Time)コンパイルと呼ばれる、いわゆるC言語などが行っている事前コンパイルを.NETおよびC#言語自体ができるようになったのです。
その、事前コンパイルが行われてる仕組みは、現在、Windowsで使われてるUWPが対象になります。また、iOS向けのC#(Xamarin)もネイティブでの実行になります。iOSは、動的言語(Javascriptは例外でできるのですが、それ以外を組み込むことができません。なので、ゲームを作ろうとしてもオリジナルスクリプトなどを組み込めないのです)を禁止しているため、中間言語方式ではなく事前に機械語(iOS系はARM系CPUアーキテクチャです)にコンパイルしているのです。
また、まだ未確認ですが、dotnet7 からAOTコンパイルが可能になったそうです。現在は、コンソールアプリのみAOTに可能なようです。
また、C#言語では2015年頃に、C#言語をインタプリタとして実行できるライブラリを提供しました。.NET Framework上のライブラリとしての提供なので、自分で書いたプログラムに簡単にインタプリがの機能を取り入れることができます。また、一部のCPU環境ではまだJITコンパイラが提供されていないものがあり、その場合の環境は、インタプリタとしてプログラムを実行します。
このように、ネイティブ(JITコンパイル、AOTコンパイル)でもインタプリタでも動かせるという多種多様な環境になっています。
ネイティブ・中間言語・インタプリタ(スクリプト)【動作形態】
ネイティブ(AOTコンパイル、JITコンパイル含むネイティブ実行)とインタプリタ(逐次実行)は「実行形態」としての考察です。実行形態は、「ネイティブ」で実行するか「インタプリタ」として実行するかの2種類しかありません。
プログラムを動作させる形態としては、3種類になります。
そして、C#言語は、すべてに対応しています。
ネイティブ(事前コンパイル)による各機械語(Intel互換(x86),AMD64互換(x64),ARM)は実行形態であげたとおり、WindowsとiOSで対応しています。C#言語には、ポインタを扱える機能があるので、Javaと比較してもネイティブとの相性はいいかもしれません。なお、ネイティブに事前にコンパイルしてあると、ある程度型情報が吹っ飛んだりする関係上(機械語には、各プログラム言語にあるオブジェクト指向のような概念などは存在しないため)、一部使える機能に制限が出たりします。
中間言語(MSIL)は、.NETの元からある機能です。基本的にネイティブ変換されない場合は、中間言語方式にコンパイルされて実行時にJITコンパイルを通して実行、AOTコンパイル(Ngen)、インタプリタで実行する形になります。Windowsでの実行形式拡張子は exe、.NET core で実行する場合は dll になります。
インタプリタ(スクリプト)とは、C#言語で書かれたコードをインタプリタに渡して解釈させ実行する形態ですが、今までのC#言語はソースコードをコンパイルして中間言語に変換し、各種実行する形態しかありませんでした...が、今のC#言語はインタプリタを内蔵させて実行させることが出来ます。
Microsoft.CodeAnalysis.CSharp.Scripting
このライブラリを入れることで、環境にインタプリタを導入できます。また、VS2015より環境自体にインタプリタのテストを出来る機能が入っています。
また、dotnet script というライブラリを導入することで、C#言語をスクリプトとして簡単に実行できます。dotnet script hogehoge.csx
。このdotnet script では、トップレベルステートメントと呼ばれる方法で記述します(C#ver9からでも利用可能です)。C#9までは、Main静的メソッドとそれを定義するためのクラスが必須でしたが、書かなくてもOKという書き方です
Console.WriteLine("Main静的メソッドとか書かなくてもOK!");
できること
GUIを持ったアプリケーションの開発
- Windows
- Mac
- Linux
- Android
- iOS
- Unity(Unityを動かせるゲーム機)
Linux/Macは、Monoを通すことで、WindowsForm も通せますし、GTK#とやらもあります。VisualStudio for Macを使うことでMac用のネイティブGUI環境も作ることが可能です。Android/iOSはネイティブのSDKで実装することも出来ますし、マルチプラットフォーム用のXamarin Formを通せば複数の端末向けに同時開発できます。また、最近UWPを利用してAndroid/iOSにも実装できるというライブラリなども出てきて、色々できるようになってきました。なお、iOSアプリを作り実機に提供するのだけは、Mac端末が必須です(作るだけならば...Macなしでもいける?)。
CUIのアプリケーション
- Windows
- Mac
- Linux
コンソールアプリケーションは、.NET coreの環境を入れられるのであればどの環境にでも実行できます。WindowsもMacもLinuxでは、今やdotnet core を使うのが主流になりつつあります。
Webアプリケーション
- ASP.NET Mvc Core
- ASP.NET Razor(ASP.NET Pages)
- ASP.NET Blazor
MacでもLinuxでも動かせますし、またMVCも可能な環境がそろっています。MVC苦手な場合は、.NET 2.0以降より、Razorのみを使うことができるようになり、ページ(Models/Controller/Viewを分ける必要がない)だけでの実装も出来るので、PHPやPerl・ASP(VBScript)など、フレームワークを特段使わないような形で作れます。
今流行りのReactやVue.jsなどのテンプレートも用意されています。(Vueはちょっと特殊な準備が必要)。SPA(Single Page Application)やPWA(Progressive Web Apps)の環境構築も意外に簡単なため、もうPHPに後戻りできません。欠点は、レンタルサーバーでは、ほぼ動作させられないという所でしょうか...。(VPSなりAWSなりで組む必要がありますね。)
あと、ASP.NET Blazorとは、WebAssemblyを通して実装できるネイティブクライアントアプリと、サーバー側でC#で実装すると、自動的にJavascriptと互換のある形に変換してくれて提供をしてくれるという実装形態(WebAssembly形式とサーバー形式で選べます。なお、.net core 3.0では後者のサーバー形式しかできません。3.1以降でWebAssembly機能ができるようです)です。
現在はまだWebAssemblyの方についてはプレビュー(試作段階)なので破壊的仕様変更もあるかと思いますが、C#言語でクライアント側のWeb実装が出来ることもあって今注目を浴びています。いろいろ試作してみているのですが、Javascript使わずに動的にテキストエリアやDOM操作が行える点はかなり最高です。Javascript、ほとんど不要ですね。唯一の大きな欠点は、デバッガが通らないのでブレイクポイントを設置できないため、結構つらい点があります。いずれ、デバッガーも通るようになるかもしれませんので、それまでは辛抱ですね。
WebAssemblyとしてコンパイル・実行させることが可能な言語はまだ少ないので、注目の一つではあります。
なお、サーバー版は、サーバー側でC#言語(MSIL)を動作させる関係上、レンタルサーバーでは無理ですね。WebAssembly版は、クライアントのブラウザ上で動かすので、配布さえすればいいだけですから、レンタルサーバーであると問題ないです(サーバ側は、PHPなどで書けば良い)
まとめ
Windowsアプリケーション開発からMac/Linuxの環境、携帯端末向けからウェブサイトまで、あらゆるアプリケーションの開発が可能になってきた.NETの環境。今ゴタゴタとなってしまっているJavaの環境を皮肉るかのように、いろんな環境でも動作できる環境になりました。
また、比較的新しい機能が取り入れられ、他の言語でも採用されたり(async/await)、逆に取り入れようとしたり(swiftのオブジェクト非null化)と、頻繁に機能が増えたり変わったりで学習するのは結構難易度が高い言語ではありますが、やっていて楽しいという点でもあり、また将来性のある言語でもあるかと思います。
今後、ウェブの行く末がネイティブのアプリを超える可能性もあり、WebAssemblyをはじめとしたSPA/PWA環境構築のための言語・環境の一つして活躍していってほしいものです。