C Sharp

C#（シーシャープ）は、マイクロソフトが開発した、汎用のマルチパラダイムプログラミング言語である。C#は、Javaに似た構文を持ち、C++に比べて扱いやすく、プログラムの記述量も少なくて済む。また、C#は、Windowsの.NET Framework上で動作することを前提として開発された言語であるが、2023年現在はクロスプラットフォームな.NETランタイム上で動作する。デスクトップ・モバイルを含むアプリケーション開発や、ASP.NETをはじめとするWebサービスの開発フレームワーク、ゲームエンジンのUnityでの採用事例などもある。

 概要 
開発にはボーランドのTurbo PascalやDelphiを開発したアンダース・ヘルスバーグを筆頭として多数のDelphi開発陣が参加している。
構文はC系言語（C言語、C++、Javaなど）の影響を受けており、その他の要素には、以前、ヘルスバーグが所属していたボーランド設計のDelphiの影響が見受けられる。また、主要言語へのasync/await構文や、ヘルスバーグが言語設計に関わるTypeScriptでのジェネリクス採用など、他言語への影響も見られる。

C#は共通言語基盤（共通言語ランタイムなど）が解釈する共通中間言語にコンパイルされて実行される。

また、C#はマルチパラダイムをサポートする汎用高レベルプログラミング言語で、静的型付け、タイプセーフ、スコープ、命令型、宣言型、関数型、汎用型、オブジェクト指向（クラスベース）、コンポーネント指向のプログラミング分野を含んでいる。他にも自動ボックス化、デリゲート、
プロパティ、インデクサ、カスタム属性、ポインタ演算操作、構造体（値型オブジェクト）、多次元配列、可変長引数、async/await構文、null安全などの機能を持つ。また、Javaと同様に大規模ライブラリ、プロセッサ・アーキテクチャに依存しない実行形態、ガベージコレクション、JITコンパイルによる実行の高速化、AOTコンパイラによる高速実行、などが実現されている（もっともこれらはC#の機能というより.NET によるものである）。

共通言語基盤 (CLI) といった周辺技術も含め、マイクロソフトのフレームワークである「.NET」の一部である。また、以前のVisual J++で「非互換なJava」をJavaに持ち込もうとしたマイクロソフトとは異なり、その多くの仕様を積極的に公開し、標準化機構に託して自由な利用を許すなど、同社の姿勢の変化があらわれている。

.NET構想における中心的な開発言語であり、XML WebサービスやASP.NETの記述にも使用される。他の.NET系の言語でも記述可能だが、.NET APIはC#からの利用を第一に想定されており、他の.NET系言語（特に2023年以降新構文の追加なしと宣言されたVB.NET）では利用できない、あるいは将来的に利用できなくなる機能が存在する。

マイクロソフトの統合開発環境(Microsoft Visual Studio)では、Microsoft Visual C#がC#に対応している。また、Visual Studio Codeに専用のC#向け拡張（C# DevKit）を導入することでクロスプラットフォームで開発することが可能。

共通言語仕様のCLSによって、他のCLS準拠の言語（F#やVisual Basic .NETやVisual C++ (C++/CLI) など）と相互に連携することができる。

 バージョンおよびリリース時期 
バージョン言語仕様リリース時期.NETVisual Studio出典と注釈ECMAISO/IECマイクロソフト公式発表個人発表その他 1.0ECMA-334:2003(2002年12月)ISO/IEC 23270:2003(2003年4月) CSharp Language Specification v1.0.doc 2002年1月 .NET rowspan=3 csharp language specification v1.2.doc 2003年4月 .NET Framework 1.1 .NET 2003 2.0 ECMA-334:2006(2006年6月) ISO/IEC 23270:2006(2006年9月) csharp 2.0 specification_sept_2005.doc 2005 3.0rowspan=2 colspan=2 CSharp Language Specification.doc 2007年11月 2008 4.0 2010年4月 .NET Framework 4 2010 rowspan=2 5.0 ECMA-334:2017(2017年12月) ISO/IEC 23270:2018(2018年12月) C# Language Specification 5.0 2012年8月 .NET Framework 4.5 6.0 ECMA-334:2022(2022年6月) rowspan=5 2015年7月 2015rowspan=4 7.0 ECMA-334:2023(2023年12月) ISO/IEC 20619:2023 (2023年9月) 2017年3月 .NET Framework 4.7 2017 version 15.0 7.1rowspan=9 colspan=2 2017年8月 .NET Core 2.0 2017 version 15.3 rowspan=3 7.2 2017年11月 .NET Core 2.0 2017 version 15.5 7.3 2018年5月 2017 version 15.7 8.0C# 8 のドラフト仕様 2019年9月 2019 version 16.3 rowspan=3 9.0機能仕様 2020年11月 .NET 5.0 2019 version 16.8 10.0 2021年12月 2022 version 17.0 11.0 2022年11月 .NET 7.0 2022 version 17.4 12.0 2023年11月 .NET 8.0 2022 version 17.8 13.0 2024年11月 .NET 9.0 2022 version 17.12 

 言語仕様 
さまざまな意味において、基盤であるCLIの機能をもっとも反映している言語であるといえる。C#にある組み込み型のほとんどは、CLIフレームワークに実装されている値型と対応している。

しかし、C#の言語仕様はコンパイラのコード生成については何も言及していないため、CLRに対応しなければならないとか、共通中間言語 (CIL) などの特定のフォーマットのコードを生成しなければならないとかいうことは述べられていない。

そのため、理論的にはC++やFORTRANのように環境依存のマシン語を生成することも可能である。しかし、現在存在するすべてのC#コンパイラはCLIをターゲットにしている。

.NET 7.0以降で可能になった事前コンパイルの一種である「Native AOT」でデプロイすることで実行可能な環境依存のバイナリを出力することが可能である。しかしながらこの手法もCLIとランタイムを事前に各アーキテクチャ向けのバイナリに変換しているだけであり、CLIを経由することに変わりはない。

特殊な例としては、UnityのScripting Backendである「IL2CPP」や「Burst」がある。
IL2CPPはC#をコンパイルしたCILをさらにC++コードへと変換後、ネイティブバイナリへC++コンパイラによってコンパイルされる。BurstはC#をコンパイルしたCILをLLVMコンパイラによってネイティブバイナリへコンパイルするものである。

 Hello World 
最新のC#ではHello Worldを下記の通りに1行で記述できる。

Console.WriteLine("Hello World!");

上記のコードは、コンパイラによって下記の様なコードに展開される。

using System;

namespace Wikipedia
{
 class Program
 {
 static void Main(string[] args)
 {
 Console.WriteLine("Hello World!");
 }
 }
}

次の言語機能によって実現されている。ただし、未対応の古いコンパイラを用いる場合は、省略できない。
 最上位レベルのステートメント
 暗黙的なusing

 CやC++からの改良点 
C#では、CやC++と比較してさまざまな制限や改良が加えられている。また、仕様の多くはC#言語というよりは、基盤である .NET そのものに依拠している。Javaで導入された制限および改良をC#でも同様に採用しているものが多いが、C#で新たに導入された改良がのちにJavaにも同様に採用されたものもある。その例を次に挙げる。

 構文や構文以外の改良点 
 外のブロックで宣言した変数と同じ名前の変数を、内のブロックで再宣言（シャドウ）してはいけない。再宣言は便利なこともあれば、混乱や曖昧のもとと主張されることもあるが、C#では禁止されている。
 C#にはブール型boolが存在し、while文やif文のように条件をとるステートメントには、bool型の式を与えなければならない。C言語では、ブール型が無くint型（0を偽とし、非0を真とする）に兼用させた上、（ヌルポインタを偽とみなすこととするといろいろと便利だった、ということもあり）ポインタでもwhile文やif文に与える式にできる、という仕様としていた。これは便利なこともあったが、本来比較式を記述すべきところで誤って代入式を記述してもコンパイル適合となってしまうなど、ミスが見逃されることもあった。C#ではに、そのような仕様ではなくブール型を独立させ、またブール型を厳密に要求する場所を多くしている。
 switch文に整数型あるいは整数型に準ずる型のみならず、文字列型stringを使用できる。caseラベルには、整数型あるいは整数型に準ずる型の定数のみならず、文字列リテラル（文字列定数）を使用できる。
 C# 7.0 以降では caseラベルに複雑なパターンマッチングを行うことが可能で複雑な判定を簡易な記述で記載が可能。
 組み込み型のサイズおよび内部表現が仕様で定められており、プラットフォームや処理系に依存しない。浮動小数点数はIEEE 754に準拠する。文字および文字列はUTF-16エンコーディングを採用する。
 C# 9.0以降では CPUによってサイズの異なる整数型 nint/nuintが追加された 
 C# 11.0 以降では文字列をUTF-8として扱う「UTF-8文字列リテラル」が追加された

 ポインタとメモリ管理 
 ポインタをサポートする。ポインタはunsafeスコープ内のみで使用することができ、適切な権限をもつプログラムのみがunsafeとマークされたコードを実行することができる。オブジェクトへのアクセスの大部分は管理された安全な参照によってなされ、大部分の算術演算はオーバフローのチェックがなされる。unsafeポインタは値型や文字列を指すことができる。セーフコードでは、必ずしもそうする必要はないものの、IntPtr型を通してポインタをやりとりすることができる。
 マネージドなメモリを明示的に解放する方法は存在せず、参照されなくなったメモリはガベージコレクタによって自動的に解放される。ガベージコレクタは、メモリの解放忘れによって起こるメモリリークを解消する。C#は、データベース接続のようなアンマネージドなリソースに対しても明示的に制御する方法を提供している。これはIDisposableインタフェースとusingステートメントまたはusing宣言によってなされる。

 名前空間とオブジェクト指向な型システム 
 グローバル変数やグローバルメソッドは存在しない。すべてのフィールドとメソッドはクラスあるいは構造体の一部として宣言されなければならない。
 例えばC/C++のprintf()関数のように名前空間レベルに存在するフリー関数を定義することはできない。ほとんどの場合クラスおよび構造体は名前の衝突を避けるために名前空間に所属する。
 名前空間は階層構造をもつ。つまり、名前空間は他の名前空間の中に宣言することができる。
 組み込みの値型を含めたすべての型は、objectクラス (System.Object) の派生型である。つまりobjectクラスのもつすべてのプロパティやメソッドを継承する。例えば、すべての型はToString()メソッドをもつ。
 クラス (class) は参照型であり、構造体 (struct) および列挙型 (enum) は値型である。構造体はクラスよりも軽量で、C/C++との相互運用性に優れるが、派生型を定義することができない。
 クラスおよび構造体は複数のインタフェースを実装することができるが、多重継承はサポートされない。
 C#はC++に比べて型安全である。既定の暗黙変換は、整数の範囲を広げる変換や、派生クラスから基底クラスへの変換といった、安全な変換のみに限定される。これは、コンパイル時、JITコンパイル時、そして一部の動的なケースでは実行時に強制される。ブール型と整数型、列挙型と整数型、の間は暗黙変換はできない。暗黙変換をユーザー定義する際は、明示的にそのように指定しなければならない。これはC++のコンストラクタとは違った仕様である。
 C#は「Null安全」である。Null許容型、Null許容参照型を持ち、Null合体演算子などの構文・演算子を持つ。
 列挙型のメンバーは、列挙型のスコープの中に置かれる。また、列挙型の定数名を取得することができる。さらに、列挙型の定数名から動的に定数値を得ることができる。
 アクセサの定義と利用を簡略化するためにプロパティ構文を利用できる。C++およびJavaにおけるカプセル化では、通例getter/setterアクセサとなるメンバー関数あるいはメソッドを定義して利用するが、C#ではプロパティ機能により、カプセル化を維持しつつ、あたかもフィールドを直接読み書きするような直感的な構文でオブジェクトの状態にアクセスすることができる。プロパティによってメンバーのアクセス制御やデータの正当性チェックを実行することができる。なお、イベントハンドラーに利用するデリゲートのカプセル化にはイベント構文 (event) が用意されている。
 ジェネリクス（総称型）の採用（C# 2.0以降）。C++のテンプレート、Javaのジェネリックスと異なりコンパイル後も型情報が保持される。また、Javaのジェネリクスと異なりプリミティブ型も型変数として使うことができる。

 C# 2.0からの仕様 

 部分型 
部分型 () が導入された。以下のようにクラスや構造体の宣言にpartial修飾子をつけることで、その宣言を分割することができる。
partial class MyClass { int a; }
partial class MyClass { int b; }
これは以下と同義である:
class MyClass { int a; int b; }
これによって、巨大なクラスを分割したり、自動生成されたコードを分離したりすることができる。partial 修飾子はすべての宣言につける必要がある。

 ジェネリクス 
ジェネリクスが導入された。これは.NET Framework 2.0の機能である。クラス、構造体、インタフェース、デリゲート、メソッドに対して適用することができる。

.NETのGenericsはC++のテンプレート、あるいはJavaにおけるそれとも異なるもので、コンパイルによってではなく実行時にランタイムによって特殊化される。これによって異なる言語間の運用を可能にし、リフレクションによって型パラメーターに関する情報を取得することができる。また、where節によって型パラメーターに制約を与えることができる。一方、C++のように型パラメーターとして式を指定することはできない。なお、ジェネリックメソッドの呼び出し時に引数によって型パラメーターが推論できる場合、型パラメーターの指定は省略できる。

 静的クラス 
静的クラスが導入された。static属性をクラスの宣言につけることで、クラスはインスタンス化できなくなり、静的なメンバーしか持つことができなくなる。

 イテレータ 
イテレータ#C# 2.0を参照。

 yieldキーワード 
yieldキーワードによるコルーチンを使うことで、イテレータの生成を楽に実装できるようになった。

 匿名デリゲート 
クロージャの機能を提供する匿名デリゲートが導入された。

 プロパティに対する個別のアクセス制御 

プロパティのget もしくは setアクセサのどちらかにアクセス修飾子を指定することでアクセス制御が別個にできるようになった。次の例では、getアクセサはpublic、setアクセサはprivateである。
public class MyClass
{
 private string status = string.Empty;
 public string Status
 {
 get { return status; }
 private set { status = value; }
 }
}

 Null許容型とnull結合演算子 
nullを保持できる値型、Nullableが導入された。
int? i = 512;
i = null;

int? j = i + 500; //jはnullとなる。nullとの演算の結果はnullになる。
int?はNullable<int>の糖衣構文である。また、nullを保持しているNull許容型のインスタンスをボックス化しようとすると、単に空参照 (null) に変換される。
int? x = null;
object o = x;
System.Console.WriteLine(o == null); //Trueが出力される

また、null結合演算子 (??)が導入された。これは、nullでない最初の値を返す。
object obj1 = null;
object obj2 = new object();
object obj3 = new object();
return obj1 ?? obj2 ?? obj3; // obj2 を返す
この演算子は主にNullable型を非Nullable型に代入するときに使われる。
int? i = null;
int j = i ?? -1; // nullをint型に代入することはできない