C Sharp

C#（シーシャープ）は、マイクロソフトが開発した汎用かつマルチパラダイムなプログラミング言語。

 概要 

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

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

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

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

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

C#は、Windowsの.NET Framework上で動作することを前提として開発された言語であった。2016年6月からはクロスプラットフォームな.NETランタイム上で動作する。Microsoft Windowsを含む複数のデスクトップ環境、ウェブアプリ・ウェブサービス（ASP.NET、ASP.NET Coreなど）、クラウドコンピューティング、モバイル、ゲーム開発（ゲームエンジンのUnityなど）などで採用されている。

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

共通言語仕様のCLSによって、他のCLS準拠の言語（F#やVisual Basic .NET、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 (2002)  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.0 rowspan=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月  2015 rowspan=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.1 rowspan=10 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.0 C# 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月8日 .NET 7.0 2022 version 17.4   12.0 2023年11月14日 .NET 8.0 2022 version 17.8   13.0 2024年11月12日 .NET 9.0 2022 version 17.12   14.0 2025年11月11日 .NET 10.0 2026 version 18.0  

 言語仕様 
、基盤である共通言語基盤（CLI）の多くの機能を反映している言語であるといえる。C#にある組み込み型のほとんどは、共通言語基盤のフレームワークに実装されている値型と対応している。

しかし、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!");
        }
    }
}

次の言語機能によって実現されている。ただし、未対応の古いコンパイラを用いる場合は、省略できない。
 C# 9.0  にて導入された最上位レベルのステートメント
 C# 10.0 にて導入された暗黙的な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属性をクラスの宣言につけることで、クラスはインスタンス化できなくなり、静的なメンバーしか持つことができなくなる。

 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型に代入することはできない

 その他 
 イテレータ
 匿名メソッド
 External Aliases/Namespace Aliases Qualifiers
 プラグマディレクティブ/C言語の様な固定長の配列表記

 C# 3.0からの仕様 

 varキーワード 
var キーワードが導入され、型推論を利用したローカル変数の宣言ができるようになった。
var s = "foo";
// 上の文は右辺が string 型であるため、次のように解釈される:
string s = "foo";
// 以下に挙げる文は誤りである（コンパイルエラーとなる）:
var v; // 初期化式を欠いている (型を推論する対象が存在しない)
var v = null; // 型が推論できない (曖昧である)

 拡張メソッド 
拡張メソッド（英: ）が導入された。既存のクラスを継承して新たなクラスを定義することなく、新たなインスタンスメソッドを疑似的に追加定義することができる。具体的には、入れ子になっていない、非ジェネリックの静的クラス内に、this 修飾子をつけた、拡張メソッドを追加する対象の型の引数を最初に持つメソッドをまず定義する。これによって、通常の静的メソッドとしての呼び出しの他に、指定した型のインスタンスメソッドとしての呼び出しを行うことができるメソッドを作ることができる。以下に例を挙げる:
public static class StringUtil
{
  public static string Repeat(this string str, int count)
  {
    var array = new string[count];
    for (var i = 0; i < count; ++i) array[i] = str;
    return string.Concat(array);
  }
}
この例は、文字列（string型のインスタンス）を指定した回数繰り返し連結したものを返すメソッドRepeatを、既存のstring型に追加している。このメソッドは、以下のように呼び出すことができる:
// 静的メソッドとしての呼び出し
StringUtil.Repeat("foo", 4);
// 拡張メソッドとしての呼び出し
"foo".Repeat(4);
// (どちらの例も "foofoofoofoo" を返す)
また、列挙型やインタフェースなど本来メソッドの実装を持ち得ない型に、見かけ上インスタンスメソッドを追加することも可能である。以下に例を挙げる:
public enum Way
{
  None, Left, Right, Up, Down
}

public static class EnumUtil
{
  public static Way Reverse(this Way src)
  {
    switch (src)
    {
      case Way.Left:  return Way.Right;
      case Way.Right: return Way.Left;
      case Way.Up:    return Way.Down;
      case Way.Down:  return Way.Up;
      default: return Way.None;
    }
  }
}
このメソッドは以下のように呼び出すことができる:
Way l = Way.Left;
Way r = l.Reverse(); // Way.Right

拡張メソッドは糖衣構文の一種であり、カプセル化の原則に違反するものではないが、必要な場合に限り注意して実装することがガイドラインとして推奨されている。

 部分メソッド 
部分メソッドが導入された。部分型（partial型）内で定義されたprivateで、かつ戻り値が voidのメソッドに partial修飾子をつけることでメソッドの宣言と定義を分離させることができる。定義されていない部分メソッドは何も行わず、何らエラーを発生させることもない。例えば:
partial class Class
{
  partial void DebugOutput(string message);

  void Method()
  {
    DebugOutput("Some message");
    Console.WriteLine("Did something.");
  }
}
上のコードにおいて Method() を呼び出すと、Did something. と表示されるだけだが、ここで以下のコード:
partial class Class
{
  partial void DebugOutput(string message)
  {
    Console.Write("[DEBUG: {0}] ", message);
  }
}
を追加した上でMethod()を呼び出すと、[DEBUG: Some message] Did something.と表示される。

 ラムダ式 
ラムダ式が導入された。この名前はラムダ計算に由来する。

以下の匿名メソッド
// iを変数としてi+1を返すメソッド
delegate (int i) { return i + 1; }
は、ラムダ式を使って次のように記述できる:
(int i) => i + 1; /* 式形式のラムダ */
//或いは:
(int i) => { return i + 1; }; /* ステートメント形式のラムダ */
ラムダ式は匿名メソッドと同様に扱えるが、式形式のラムダがExpression<TDelegate>型として扱われた場合のみ匿名メソッドとして扱われず、コンパイラによって式木を構築するコードに変換される。匿名デリゲートが実行前にコンパイルされたCILを保持するのに対し、式木はCILに実行時コンパイル可能であるDOMのような式の木構造そのものを保持する。これはLINQクエリをSQLクエリなどに変換する際に役立つ。

以下は、3つの任意の名前の変数、整数、括弧、及び四則演算子のみで構成された式を逆ポーランド記法に変換する汎用的なコードである:
public static string ToRPN(Expression<Func<int, int, int, int>> expression)
{
  return Parse((BinaryExpression) expression.Body).TrimEnd(' ');
}

private static string Parse(BinaryExpression expr)
{
  string str = "";

  if (expr.Left is BinaryExpression)
  {
    str += Parse((BinaryExpression) expr.Left);
  }
  else if (expr.Left is ParameterExpression)
  {
    str += ((ParameterExpression) expr.Left).Name + " ";
  }
  else if (expr.Left is ConstantExpression)
  {
    str += ((ConstantExpression) expr.Left).Value + " ";
  }

  if (expr.Right is BinaryExpression)
  {
    str += Parse((BinaryExpression) expr.Right);
  }
  else if (expr.Right is ParameterExpression)
  {
    str += ((ParameterExpression) expr.Right).Name + " ";
  }
  else if (expr.Right is ConstantExpression)
  {
    str += ((ConstantExpression) expr.Right).Value + " ";
  }

  return str + expr.NodeType.ToString()
    .Replace("Add", "+")
    .Replace("Subtract", "-")
    .Replace("Multiply", "*")
    .Replace("Divide", "/")
    + " ";
}

// 呼び出し例:
ToRPN((x, y, z) => (x + 1) * ((y - 2) / z)); // "x 1 + y 2 - z / *" を返す

 オブジェクト初期化の簡略化 
オブジェクトの初期化が式として簡潔に記述できるようになった。
var p = new Point { X = 640, Y = 480 };
// 上の文は次のように解釈される:
Point __p = new Point();
__p.X = 640;
__p.Y = 480;
Point p = __p;
また、コレクションの初期化も同様に簡潔に記述できるようになった。
var l = new List<int> {1, 2, 3};
var d = new Dictionary<string, int> {{"a", 1}, {"b", 2}, {"c", 3}};
// 上の文は次のように解釈される:
List<int> __l = new List<int>();
__l.Add(1);
__l.Add(2);
__l.Add(3);
List<int> l = __l;
Dictionary<string, int> __d = new Dictionary<string, int>();
__d.Add("a", 1);
__d.Add("b", 2);
__d.Add("c", 3);
Dictionary<string, int> d = __d;
但し、上のコードでは匿名の変数に便宜的に __p、__l、__d と命名している。実際はプログラマはこの変数にアクセスすることはできない。

 自動実装プロパティ 
プロパティをより簡潔に記述するための自動実装プロパティが導入された。プロパティの定義にget; set;と記述することで、プロパティの値を保持するための匿名のフィールド（プログラマは直接参照することはできない）と、そのフィールドにアクセスするためのアクセサが暗黙に定義される。また、C# 5.0までは get;とset;のどちらか片方だけを記述することは出来なかったが、C# 6.0からはget;のみが可能。以下のコード:
public int Value { get; set; }
は、以下のようなコードに相当する動作をする:
private int __value;
public int Value
{
  get { return __value; }
  set { __value = value; }
}
但し、上のコードでは匿名のフィールドに便宜的に__valueと命名している。実際はプログラマはこのフィールドにアクセスすることはできない。

 匿名型 
一時的に使用される型を簡単に定義するための匿名型が導入された。以下に例を挙げる:
new { Name = "John Doe", Age = 20 }
上の式は、以下の内容のクラスを暗黙に定義する。定義されたクラスは匿名であるが故にプログラマは参照できない。
public string Name { get; }
public int Age { get; }
同じ型、同じ名前のプロパティを同じ順序で並べた匿名型は同じであることが保証されている。即ち、以下のコード:
var her = new { Name = "Jane Doe", Age = 20 }
var him = new { Name = "John Doe", Age = 20 }
において、her.GetType() == him.GetType()はtrueである。

 配列宣言の型省略 
newキーワードを用いた配列の宣言の際、型を省略できるようになった。匿名型の配列を宣言する際に威力を発揮する。
var a = new[] {"foo", "bar", null};
// 上の文は次のように解釈される:
string[] a = new string[] {"foo", "bar", null};
// 以下の文:
var a = new[] {"foo", "bar", 123};
// は次のように解釈されることなく、誤りとなる:
object[] a = new object[] {"foo", "bar", 123};

 クエリ式 
LINQをサポートするために、クエリ式が導入された。これはSQLの構文に類似しており、最終的に通常のメソッド呼び出しに変換されるものである。以下に例を示す:
var passedStudents =
  from s in students
  where s.MathScore + s.MusicScore + s.EnglishScore > 200
  select s.Name;
上のコードは以下のように変換される:
var passedStudents = students
  .Where(s => s.MathScore + s.MusicScore + s.EnglishScore > 200)
  .Select(s => s.Name);
C# 3.0で追加された構文の多くは式であるため、より巨大な式（当然クエリ式も含まれる）の一部として組み込むことができる。旧来複数の文に分けたり、作業用の変数を用意して記述していたコードを単独の式としてより簡潔に記述できる可能性がある。

出井秀行著の『実戦で役立つ C#プログラミングのイディオム/定石&パターン』（技術評論社、2017年）という書籍ではクエリ構文よりメソッド構文を推奨しており、クエリ構文ではLINQの全ての機能を使用できるわけではないこと、メソッド呼び出しは処理を連続して読める可読性があること、メソッド呼び出しであればMicrosoft Visual Studioの強力なインテリセンスが利用できることを理由に、著者はクエリ構文をほとんど使用していないと記している。

 C# 4.0からの仕様 

 dynamicキーワード 
dynamicキーワードが導入され、動的型付け変数を定義できるようになった。dynamic型として宣言されたオブジェクトに対する操作のバインドは実行時まで遅延される。
// xはint型と推論される:
var x = 1; 
// yはdynamic型として扱われる:
dynamic y = 2; 

public dynamic GetValue(dynamic obj)
{
  // objにValueが定義されていなくとも、コンパイルエラーとはならない:
  return obj.Value;
}

 オプション引数・名前付き引数 
VBやC++に実装されているオプション引数・名前付き引数が、C#でも利用できるようになった。
public void MethodA()
{
  // 第1引数と第2引数を指定、第3引数は未指定:
  Console.WriteLine("Ans: " + MethodB(1, 2));  // Ans: 3 … 1 + 2 + 0となっている

  // 第1引数と第3引数を指定、第2引数は未指定:
  Console.WriteLine("Ans: " + MethodB(A: 1, C: 3));  // Ans: 4 … 1 + 0 + 3となっている
}

// 引数が指定されなかった場合のデフォルト値を等号で結ぶ:
public int MethodB(int A = 0, int B = 0, int C = 0)
{
  return A + B + C;
}

 ジェネリクスの共変性・反変性 
ジェネリクスの型引数に対してin、out修飾子を指定することにより、ジェネリクスの共変性・反変性を指定できるようになった。
IEnumerable<string> x = new List<string> { "a", "b", "c" };
// IEnumerable<T>インターフェイスは型引数にout修飾子が指定されているため、共変である。
// したがって、C# 4.0では次の行はコンパイルエラーにならない
IEnumerable<object> y = x; 

 C# 5.0からの仕様 
 非同期処理（Async/await）
 呼び出し元情報属性
 foreach の仕様変更

 C# 6.0からの仕様 
 自動実装プロパティの初期化子
 getのみの自動実装プロパティおよびコンストラクタ代入

 静的usingディレクティブ
 インデックス初期化子
 catch/finallyでのawait
 例外フィルタ
 式形式のメンバー（expression-bodied members）
 null条件演算子
 文字列補間（テンプレート文字列）
 nameof演算子
 #pragma
 コレクションの初期化子での拡張メソッド
 オーバーロード解決の改善

 静的 using ディレクティブ 
静的usingディレクティブを利用することで、型名の指定無しに他クラスの静的メンバーの呼び出しを行えるようになった。利用するにはusing staticの後に完全修飾なクラス名を指定する。

using static System.Math;
// ↑ソースコードの上部で宣言
class Hogehoge {
    // System.Math.Pow() , System.Math.PI を修飾無しで呼び出す
    double area = Pow(radius, 2) * PI;
}

 例外フィルタ 
catchの後にwhenキーワードを使用することで、処理する例外を限定することができるようになった。

try {
    // ...
}
catch (AggregateException ex) when (ex.InnerException is ArgumentException) {
    // ...
}

 C# 7.0からの仕様 
 出力変数宣言
 パターンマッチング（is式/switch文）
 タプル（タプル記法/分解/値の破棄）
 ローカル関数
 数値リテラルの改善（桁セパレータ/バイナリリテラル）
 ref戻り値、ref変数
 非同期戻り値型の汎用化
 Expression-bodied機能の拡充（コンストラクタ/デストラクタ/get/set/add/remove）
 Throw式

 出力変数宣言 
out引数で値を受け取る場合、その場所で変数宣言可能となった。

total += int.TryParse("123", out var num) ? num : 0;

 パターンマッチング 

 is 式の拡張 
is式の構文が拡張され、型の後ろに変数名を宣言できるようになった。拡張されたis式はマッチした場合に宣言した変数にキャストした値を代入し、さらにtrueと評価される。マッチしなかった場合はfalseと評価され、宣言した変数は未初期化状態となる。

void CheckAndSquare(object obj) {
    // objの型チェックと同時にnumに値を代入する。
    if (obj is int num && num >= 0) {
        num = num * num;
    }
    else {
        num = 0;
    }
    // if文の条件セクションは、ifの外側と同じスコープ
    Console.WriteLine(num);
}

 switch 文の拡張 
switch文のマッチ方法が拡張され、caseラベルに従来の「定数パターン」に加え、新たに「型パターン」を指定できるようになった。また、「型パターン」のcaseラベルでは、when句に条件を指定することができる。「型パターン」を含むswitch文では、必ずしも条件が排他的でなくなったため、最初にマッチしたcaseラベルの処理が実行される。

void Decide(object obj) {
    switch (obj) {
        case int num when num < 0:
            Console.WriteLine($"{num}は負の数です。");
            break;
        case int num:
            Console.WriteLine($"{num}を二乗すると{num * num}です。");
            break;
        case "B":
            Console.WriteLine($"これはBです。");
            break;
        case string str when str.StartsWith("H"):
            Console.WriteLine($"{str}はHから始まる文字列です。");
            break;
        case string str:
            Console.WriteLine($"{str}は文字列です。");
            break;
        case null:
            Console.WriteLine($"nullです");
            break;
        default:
            Console.WriteLine("判別できませんでした");
            break;
    }
}

 タプル 
タプルのための軽量な構文が導入された。従来のSystem.Tupleクラスとは別に、System.ValueTuple構造体が新しく追加された。

 タプル記法 
2個以上の要素を持つタプルのための記法が導入された。引数リストと同様の形式で、タプルを記述できる。

// タプル記法
(int, string) tuple = (123, "Apple");
Console.WriteLine($"{tuple.Item1}個の{tuple.Item2}");

 分解 
多値戻り値を簡単に扱えるように、分解がサポートされた。

var tuple = (123, "Apple");
// 分解
(int quantity, string name) = tuple;
Console.WriteLine($"{quantity}個の{name}");

分解はタプルに限らない。Deconstruct()メソッドが定義されたクラスでも、分解を利用できる。

以下に、DateTime型に分解を導入する例を示す。

static class DateExt {
    public static void Deconstruct(this DateTime dateTime, out int year, out int month, out int day) {
        year = dateTime.Year;
        month = dateTime.Month;
        day = dateTime.Day;
    }
}
上記のコードでDateTime型にDeconstruct()拡張メソッドを定義し、
// 分解
(int year, int month, int day) = DateTime.Now;
のように左辺で3つの変数に値を受け取ることができる。

 値の破棄 
分解、out引数、パターンマッチングで、値の破棄を明示するために_が利用できるようになった。破棄された値は、後で参照することはできない。

// 年と日は使わない
(_, int month, _) = DateTime.Now;

// 解析結果だけ取得し、変換された値は使わない
bool isNumeric = int.TryParse(str, out _);

switch (obj) {
    // string型で分岐するが、値は使わない
    case string _:
        // Do something.
        break;
}

 ref戻り値、ref変数 
refキーワードの使用方法が拡張された。これによって、安全な参照の使い道が広がった。

 ref戻り値 
戻り値の型をrefで修飾することで、オブジェクトの参照を戻り値とすることができる。

// 二つの参照引数の内、値の大きいものの参照戻り値を返す
static ref int Max(ref int left, ref int right) {
    if (left >= right) {
        return ref left;
    }
    else {
        return ref right;
    }
}

変数の寿命は変わらないため、メソッド終了時に破棄されるローカル変数をref戻り値とすることはできない。

static int s_count = 1;

// メンバーの参照はref戻り値になる。
static ref int ReturnMember() {
    return ref s_count;
}
// ref引数はもちろんref戻り値になる。
static ref int ReturnRefParam(ref int something) {
    return ref something;
}
// ローカル変数をref戻り値とすることはできない。
// static ref int ReturnLocal() {
//     int x = 1;
//     return ref x;
// }

 ref変数 
ローカル変数の型をrefで修飾することで、参照を代入することができる。

// 参照戻り値を参照変数で受け取る
ref int max = ref Max(ref x, ref y);
// limitとmaxは同じ値を参照する
ref int limit = ref max;

 C# 7.1からの仕様 
 非同期なMainメソッド 
Mainメソッドの戻り値として、Task型、Task(int)型が認められた。
static Task Main()
static Task<int> Main()
 default式 
型推論可能な場面では、defaultの型指定は省略可能となった。
int number = default;
string name = default;

 C# 7.2からの仕様 
C#7.2で追加された仕様は以下の通り。

 値型の参照セマンティクス 
値型におけるパフォーマンス向上を意図した複数の機能が追加された。

 in参照渡し、ref readonly参照戻り値 
引数にinを指定することで、読み取り専用参照渡しを指定できる。また、戻り値にref readonlyを指定することで、読み取り専用参照戻り値を指定できる。

これにより、構造体のコピーを避けると共に、意図しない値の変更を抑止できる。

 readonly構造体 
構造体宣言時にreadonlyを指定することで、真の読み取り専用構造体を定義できる。readonly構造体の全てのフィールドはreadonlyでなければならず、thisポインタも読み取り専用となる。

これにより、メンバーアクセス時の意図しない防御的コピーを抑止できる。

 ref構造体 
構造体宣言時にrefを指定することで、ヒープ領域へのコピーを防ぐ構造体がサポートされる。ref構造体では、box化できない、配列を作成できない、型引数になることができない、など、ヒープ領域へのコピーを防ぐための厳しい制限がかかる。

この機能は、Span<T>のような構造体をサポートするために利用され、unsafe文脈以外でのstackallocの利用をも可能とする。

 末尾以外の場所での名前付き引数 
C#4.0で追加された名前付き引数が末尾以外でも利用できるようになった。

Hogehoge(name: "John", 17);

 private protected アクセス修飾子 
同一アセンブリ内、かつ、継承先からのアクセス許可を表すprivate protectedアクセス修飾子が追加された。

 数値リテラルの改善 
十六進リテラルの0x、二進リテラルの0bの直後のアンダースコアが認められた。

int bin = 0b_01_01;
int hex = 0x_AB_CD;

 C# 7.3からの仕様 
C#7.3では以下の仕様が追加された。

 ジェネリック型制約の種類の追加
 System.Enum、System.Delegate
 unmanaged（文脈キーワード）

unsafe class MyGenericsClass<T1,T2,T3> 
    where T1 : System.Enum
    where T2 : System.Delegate
    where T3 : unmanaged {

    public MyGenericsClass(T1 enum1, T1 enum2, T2 func, T3 unmanagedValue) {
        if (enum1.HasFlag(enum2)) {
            func.DynamicInvoke();
        }
        else {
            T3* ptr = &unmanagedValue;
        }
    }
}

 refローカル変数の再割り当て
 stackalloc初期化子
 Indexing movable fixed buffers
 カスタムfixedステートメント
 オーバーロード解決ルールの改善
 出力変数宣言の利用箇所の追加

class MyOutVar {
    // メンバー変数初期化子やコンストラクタ初期化子で出力変数宣言が可能
    readonly int x = int.TryParse("123", out var number) ? number : -1;
}

 タプル同士の比較

(long, long) tuple = (1L, 2L);
// タプルのすべての要素間で == が比較可能
if (tuple == (1, 2)) { }
// 要素数が異なるタプル同士は比較できない。
//if (tuple == (1, 2, 3)) { }

 バッキングフィールドに対するAttribute指定

// C#7.2までは無効な指定(コンパイル自体は可能。無視される)
// C#7.3からはバッキングフィールドに対するAttribute指定と見なされる
[field: NonSerialized]
public int MyProperty { get; set; }

 C# 8.0からの仕様 

C# 8.0で追加された仕様は以下の通り。

 null許容参照型 

参照型にnull許容性を指定できるようになった。参照型の型名に?を付加した場合にnull許容参照型となる。

参照型の型名に?を付加しない場合、null非許容参照型となる。

フロー解析レベルでのnull許容性チェックが行われる。null許容値型のNullable<T>のような新しい型は導入されない。

 null許容コンテキスト 

参照型のnull許容性は、null許容コンテキストによって有効、無効の切り替えが可能である。C#7.3以前の互換性のために、既定では無効となっている。

 Nullable コンパイルオプション： プロジェクト全体でのnull許容コンテキストを指定する
 #nullable ディレクティブ： ソースコードの部分ごとにnull許容コンテキストを指定する
 annotations オプション、warningsオプションにより、適用範囲を限定できる

 null免除演算子 

null許容参照型の変数名の後に !を使用することで、フロー解析時の警告が免除される。

 インタフェースの既定メンバー 

インタフェースのメンバーに既定の実装を指定できるようになった。また、インタフェースに静的メンバーを持つことができるようになった。

さらに、インタフェースのメンバーにアクセシビリティを指定できるようになった。

 既定のアクセシビリティは、従来通り public となる。
 実装があるインスタンスメンバーは、既定で virtual となり override可能である。
 実装をoverrideさせないためにsealedを指定することができる。

 パターンマッチングの拡張 (C# 8.0) 

switch式が追加された。プロパティパターン、タプルパターン、位置指定パターンの追加により、再帰的なパターンマッチングが可能になった。

 switch式
 再帰パターン
 プロパティパターン
 タプルパターン
 位置指定パターン

 非同期ストリーム 

IAsyncEnumerable<T>インタフェースを返すことで、イテレータ構文と非同期構文の共存が可能になった。

async IAsyncEnumerable<int> EnumerateAsync() {
    await Task.Delay(100);
    yield return 1;
    await Task.Delay(100);
    yield return 2;
}

await foreachによって非同期ストリームを列挙する。

async void SpendAsync() {
    await foreach (var item in EnumerateAsync()) {
        Console.WriteLine(item);
    }
}

 範囲指定 

IndexとRangeを指定できる専用構文が追加された。

  Index a = 1; // new Index(1, fromEnd: false)
  Index b = ^1; // new Index(1, fromEnd: true)
  Range range = a..b; // new Range(start: a, end: b)

 その他の仕様 

 静的ローカル関数
 null結合代入演算子
 構造体の読み取り専用メンバー
 using 宣言
 ref構造体のDispose
 ジェネリクスを含むアンマネージ型
 式中のstackalloc
 文字列補間のトークン順序の緩和

 C# 9.0からの仕様 

C# 9.0で追加された仕様は以下の通り。

 レコード
 プロパティのinitアクセサ
 最上位レベルステートメント
 パターンマッチングの拡張
 new式の型推論
 条件演算子の型推論
 共変戻り値
 GetEnumeratorの拡張メソッド対応
 静的匿名関数
 ラムダ式引数の破棄
 ローカル関数への属性適用
 パフォーマンスと相互運用
 ネイティブサイズの整数型（nint型、nuint型）
 関数ポインタ（delegate*型）
 変数初期化フラグの抑制
 コードジェネレータのサポート
 モジュール初期化子
 部分メソッドの拡張
 C# 10.0からの仕様 

C# 10.0で追加された仕様は以下の通り。

 レコード構造体
 構造体型の機能強化
 補間された文字列ハンドラー
 global using ディレクティブ
 ファイル スコープの名前空間の宣言
 拡張プロパティのパターン
 ラムダ式の機能強化
 const 補間文字列を許可する
 レコードの型で ToString() を封印できる
 限定代入の機能強化
 同じ分解で代入と宣言の両方を許可する
 メソッドで AsyncMethodBuilder 属性を許可する
 CallerArgumentExpression 属性
 拡張 #line pragma
 警告ウェーブ 6

 C# 11.0からの仕様 
C# 11.0で追加された仕様は以下の通り。

 生文字列リテラル 
エスケープなどの加工を施さない生の文字列を、3個以上の二重引用符で括る事で表現できる様になった。未加工の文字列リテラルとも呼ばれる。生文字列中には、その文字列を括っている二重引用符より少ない数で連続した二重引用符を普通の文字として埋め込む事ができる。文字列の開始を示す二重引用符の直後に何らかの文字列が記述されているかどうかで単一行か複数行かが弁別される。

単一行の場合は、"""あいうえお"かきくけこ"さしすせそ"""の様に記述でき、これはを表す。文字列中に3個の二重引用符を含める場合は""""たちつてと"""なにぬねの""""などと書ける。

複数行の場合において開始を示す二重引用符の直後は、空白または改行のみが受け付けられ、次の行が実際の一行目となる。複数行の生文字列の行はインデントする事ができ、文字列の終了を示す二重引用符のインデント位置と同等の空白文字とタブ文字が全ての行から削除される。その為、終了を示す二重引用符は、最終行の次の行にインデントと伴に置かなければならず、途中の行をこのインデント位置より浅くするとコンパイルエラーになる。

複数行の生文字列の記述例は次の通り。
string logMsg = """
	原因不明のエラーが発生しました。
	詳細はログファイル "C:\Logs\exception.log" を確認してください。
	""";

開始を示す二重引用符の直前に任意の数の$を置く事で、補間文字列の機能を用いる事もできる。式を埋め込むには$と同数の半角波括弧（{と}）で括らなければならない。$より少ない数で連続した波括弧は普通の文字として扱われ、$より多い数で連続させるとコンパイルエラーになる。

 汎用属性 
属性の型が型引数を持てる様になった。
// 属性
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class ConverterContractAttribute<TFrom, TTo> : Attribute { }

// 使用例
[ConverterContract<byte, string>()]
[ConverterContract<sbyte, string>()]
[ConverterContract<short, string>()]
[ConverterContract<ushort, string>()]
[ConverterContract<int, string>()]
[ConverterContract<uint, string>()]
[ConverterContract<long, string>()]
[ConverterContract<ulong, string>()]
public class IntToStringConverter
{
	// ...
}

 パターンマッチングの拡張 (C# 11.0) 
リストや配列に対するパターンマッチが可能になった。
int[] nums = new[] { 0, 1, 2, 3, 4, 5 };

if (nums is [ 0, 1, 2, .. ]) {
	Console.WriteLine("配列は 0, 1, 2 から始まります。");
} else {
	Console.WriteLine("配列は 0, 1, 2 から始まりません。");
}
また、Span<char>やReadOnlySpan<char>に対して文字列を用いたパターンマッチが可能になった。
bool CheckSignature(ReadOnlySpan<char> sig)
	=> sig is "HOGE";

 ジェネリック型数値演算 
型引数に「数値型または数値型に類似している型」である事を示す制約を付け加える機能が導入された。また、それに呼応して下記の変更が行われた。
明示的な論理シフト演算子（>>>演算子）が追加された。
シフト演算子の右側の引数の型に対する制限の撤廃され、int型以外の型を指定できる様になった。
checked演算子のオーバーロードができる様になった。
インターフェースのメソッドに対してstatic abstractキーワード（静的抽象）とstatic virtualキーワード（静的仮想）を指定できる様になった。
インターフェース内に演算子を定義できる様になった。
ジェネリック型数値演算を用いた一例を下記に示す。
// 大抵の演算子インターフェイスは System.Numerics 内に実装されている。
using System.Numerics;

// 任意の型に対して加算を行う事ができる関数。
static T MyAdd<T>(T value1, T value2)
	where T: IAdditionOperators<T, T, T> // 加算が可能な型のみを受け付ける制約。
	=> value1 + value2; // + 演算子を使う事ができる。

// 上記の関数定義のみで、下記の様に加算演算が定義された型であれば、任意の型で呼び出す事ができる。
int    a = MyAdd(  123,   456); // 結果：579
ulong  b = MyAdd(111UL, 222UL); // 結果：333
double c = MyAdd( 1.5D,  2.1D); // 結果：3.6

 その他の仕様 
 UTF-8 文字列リテラル
 文字列補間式の改行
 ファイルローカル型
 必須メンバー
 auto-default 構造体（構造体の未初期化のフィールド変数が自動的に既定値に初期化される）
 nameofのスコープ拡張
 IntPtrに別名 nint、UIntPtrに別名 nuintが付いた
 refフィールド
 scoped ref変数
 メソッドグループからデリゲートへの変換の改善
 警告ウェーブ 7

 C# 12.0からの仕様 
C# 12.0で追加された仕様は以下の通り。

 クラスと構造体のプライマリコンストラクター 

レコード型（record）以外のクラス（class）と構造体（struct）でプライマリコンストラクターが使えるようになった。

class Example(string message) 
{
    public string Message { get; } = message;
}

 コレクション式 

配列、コレクション、Span<T>などの初期化の記法が共通の記法（[]）で書けるようになった。

// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];

// Create a list:
List<string> b = ["one", "two", "three"];

// Create a span
Span<char> c  = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];

 スプレッド演算子 

コレクション式で複数のコレクションをインライン展開できる新しい演算子（..）が追加された。

int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
// 1, 2, 3, 4, 5, 6, 7, 8, 9,
int[] single = [.. row0, .. row1, .. row2];

 その他の仕様 
 インライン配列 
 既定のラムダパラメーター
 任意の型の別名設定
 ref readonlyパラメーター
 試験段階の属性
 インターセプター

 C# 13.0からの仕様 
C# 13.0で追加された仕様は以下の通り。

 新しいエスケープシーケンス 
エスケープ文字を表すエスケープシーケンスとして\eが追加された。これに従って\x1bの使用は非推奨となった。

 暗黙的なインデックスアクセス 
オブジェクト初期化子においても^演算子を用いたアクセスが可能となった。これにより、初期化子内でも配列やリストなどの末尾から値へアクセスできる。

 params コレクション 
コレクション式に対応している型であれば、引数にparams修飾子を付けられる様になった。

// 関数定義
void Print(string format, params IEnumerable<object> args)
{
    /* ... 任意の実装 ... */

    // 例えば
    Console.WriteLine(format, args.ToArray());
}

// 呼び出し
int a = 2, b = 3;
Print("{0} + {1} = {2}", a, b, a + b);

 部分プロパティ 
プロパティとインデクサにもpartial修飾子の指定が可能となった。

public partial bool IsThisPartialProperty { get; }

public partial char this[int index] { get; }

 Lock クラスに対する lock 
任意のオブジェクトで排他制御される問題への対策として、lock文専用のLockクラスが用意された。以下の様に使う。

var lockObj = new Lock();

lock (lockObj) {
    // 排他制御されるコード
}

// このコードは、コンパイラによって次の形に展開される：
using (lockObj.EnterScope()) {
    // 排他制御されるコード
}

 その他の仕様 
 メソッド グループでの自然型
 ref 構造体のインターフェイス実装
 OverloadResolutionPriority 属性（オーバーロードの解決優先度を変更できる）
 イテレーター・非同期メソッド内の ref/unsafe
 インターセプター
 コレクション式の改善

 C# 14.0からの仕様 
C# 14.0で追加された仕様は以下の通り。

 拡張メンバー 
新たに extension ブロックが導入され、拡張プロパティと拡張インデクサーを実装できる様になった。この機能は、拡張メンバー（英: ）または拡張宣言（英: ）などと呼称される。特定の型に対してメンバーを外部の型から後付する事ができる。型引数を受け取るには、extension キーワードの後ろに <T> と記述する。また、動的メンバーだけではなく静的メンバーを追加する事もできる。

整数型に新たなプロパティを追加するコードを以下に示す。
static class Some
{
    extension(int arg)
    {
        public int Twice => arg << 1;
        public int Half  => arg >> 1;
    }
}

 プロパティにおける field キーワード 
プロパティのアクセサー内で field キーワードを用いる事でバッキングフィールドを自動生成できる。従ってプロパティ専用の変数を新たに定義する必要は無い。既に field という名称の変数が存在する場合、代わりに @field または this.field と記述しなければならない。

get アクセサーのみで用いる場合は以下の様に記述できる。
class Some
{
    public object? Data { get => field ?? new(); set; }
}

対して、set アクセサーのみで用いる場合は以下の様に記述できる。
class Some
{
    public int Number { get; set => value = field + 1; }
}

両方のアクセサーで同時に用いる事も、set の代わりに init 内で用いる事も、従来通り get; set; と記述する事もできる。バッキングフィールドに属性を付与する場合は、プロパティ宣言の直前に [field: AttributeClassName()] と記述する。

 null 条件付き割り当て 
null 条件演算子を代入演算子の左辺でも用いられる様になった。

例えば、次の様なクラスが定義されているものとする。
class Some
{
    public string? Name { get; set; }
}

通常は、if 文を用いて null ではない場合にのみ代入処理が実施される様にしなければならない。
void SetName(Some? obj, string? name)
{
    if (obj is not null) {
        obj.Name = name;
    }
}

新しい演算子によって、変数の検証を略記できる様になった。
void SetName(Some? obj, string? name)
{
    obj?.Name = name;
}

 複合代入演算子のユーザー定義 
複合代入演算子の動作を上書きできる様になった。コピーコストの削減が目的である。他の演算子と同じ書式で定義できる。

public void operator +=(int arg) { /* ... ここに具体的なコードを書く ... */ }

 その他の仕様 
 nameof の拡張（引数無しのジェネリック型にも対応）
 暗黙的な Span<T> と ReadOnlySpan<T> の変換
 ラムダ式の引数の修飾子（主に参照渡し関係）
 partial の拡張（部分コンストラクタと部分イベント）

 実装 
C#の言語仕様は標準化団体Ecma Internationalを通じて公開・標準化されており、第三者がマイクロソフトとは無関係にコンパイラや実行環境を実装することができる。

 コンパイラの実装 
 マイクロソフト製
 Visual Studio 2015 以降で使用されている、（コードネームRoslyn）。ApacheライセンスのオープンソースプロジェクトでGitHubで公開されている。Windows、macOS、Linuxで動作する。C#のコンパイラはC#、VB.NETのコンパイラはVB.NETで実装されている。以前のコンパイラと比べて、リファクタリングやIDE、スクリプティングなどへの利用が可能なAPIが公開されており、コンパイラ以外への様々な応用が可能。
 Visual Studio 2013 まで使われていた、マイクロソフトによるVisual C# コンパイラ。
 2006年のC# 2.0当時の、マイクロソフトによるShared Source Common Language Infrastructure。共通言語基盤（CLI）とC#コンパイラがソースコードで公開されている。
 Mono ProjectによるMono内の Mono Compiler Suite (mcs)。
 2012年まで開発されていた、DotGNU ProjectによるPortable.NET内の the C-Sharp code compiler (cscc)。

 実行環境の実装 

 マイクロソフト
 .NET Runtime
 .NET Framework Runtime
 Mono Project
 Monoランタイム
 カプコン
 RE ENGINEに実装されている REVM

 名称 
ECMA-334 3rd/4th/5th edition によると、C# は「C Sharp（シーシャープ）」と発音し、LATIN CAPITAL LETTER C (U+0043)の後に NUMBER SIGN # (U+0023)と書くStandard ECMA-334 C# Language Specification。MUSIC SHARP SIGN ♯ (U+266F) ではなく NUMBER SIGN # (U+0023)を採用したのは、フォントやブラウザなどの技術的な制約に加え、ASCIIコードおよび標準的キーボードには前者の記号が存在しないためである。

「#」を接尾辞とする名称は、他の .NET 言語にも使用されており、J#（Javaのマイクロソフトによる実装）、（Adaから）、F#（System FなどからThe A-Z of programming languages: F# | Network World）が含まれる。更には、Gtk#（GTK などの GNOME ライブラリの .NET ラッパ）、（Cocoa のラッパ）などのライブラリにも使用されている。そのほか、SharpDevelopなどの「Sharp」を冠する関連ソフトウェアも存在する。

C# という名称の解釈として、「（A-Gで表された）直前の音を半音上げる」という音楽記号の役割に着目し、「C言語を改良したもの」を意味したのではないか、。これは、C++の名称が「C言語を1つ進めたもの」という意味でつけられたことにも似ている。アンダース・ヘルスバーグは、「C#」が「C++++」（すなわち「C++ をさらに進めたもの」）にみえるのが由来である、と語っているレポート：コミュニティスペシャルセッション with Anders Hejlsberg in Microsoft Developers Conference 2006C#への期待。アンダースからの返答。

 脚注 
 注釈 

 出典 
 公式発表 

 個人サイト 

 その他 

 参考文献 



 関連項目 
 言語仕様

 C#のデータ型
 キーワード (C#)
 実行環境
 .NET  (旧：.NET Core)
 .NET Framework
 Mono
 Xamarin
 開発環境
 Visual Studio
 Visual C#
 Visual Studio Code
  - ジェットブレインズ社の.NET向け統合開発環境
 MonoDevelop  - OSSの統合開発環境
 Xamarin Studio
 Visual Studio for Mac
 SharpDevelop - フリーの統合開発環境
 比較
 C#とJavaの比較

 外部リンク 
 C# 関連のドキュメント - はじめに、チュートリアル、リファレンス。 | Microsoft Docs - 公式ウェブサイト（日本語）
 言語仕様
 Introduction - C# language specification | Microsoft Learn - C# 言語仕様、Microsoft Docs
 ECMA-334 - Ecma International ECMA-334 C# 言語仕様

 C# Compiler | Mono Mono C# コンパイラ

Category:.NET
Category:並行計算
Category:C Sharp