C Sharpその他 - C Sharpのバージョン
概要
ここでは、C# 4.0以降におけるバージョンごとの新機能について記載する。
下図に、Visual StudioとC#、.NET Frameworkの関係を示す。
.NET Framework 2.0以降のバージョンアップにおいて、多くがライブラリの追加のみといえる。
- .NET Framework 1.1 … バグ修正のみ
- .NET Framework 2.0 … ジェネリックなコレクション追加
- .NET Framework 3.0 … WPF、WCF、WF 等追加
- .NET Framework 3.5 … LINQ 関連のライブラリ、ASP.NET AJAX 追加
- .NET Framework 3.5 SP1 … ADO.NET Entity Framework 等追加
- .NET Framework 4 … dynamic 関連、並列処理関連の追加
- .NET Framework 4.5 … async/await 関連の追加
.NET Framework 3.0〜3.5 SP1のバージョンアップが細かい理由として、新機能をできるだけ早く提供してほしいという要望のためである。
.NET Framework 4以降は、NuGetパッケージマネージャ等が誕生したこともあり、.NET Frameworkとは別にライブラリ提供するようになった。
.NET 5(.NET Frameworkは廃止)では、NuGetパッケージマネージャによる配布が本格化しており、.NET 5ならではの機能はもはや明確ではない。
C# 4.0の新機能
- リリース時期
- 2010/4
- 同世代技術
- Visual Studio 2010
- .NET Framework 4
- Visual Basic 10
- 要約・目玉機能
- dynamic
- 相互運用
C# 4.0で追加される機能は以下の3つである。
- 動的型付け変数
- オプション引数 / 名前付き引数
- ジェネリクスの共変性・反変性
動的型付け変数 : dynamicキーワード
dynamicキーワードを使用することで、動的型付け変数を定義できる。
この機能は、コンパイル時に確定しないプロパティアクセスやメソッドの呼び出しができる。
主な使用用途において、スクリプト言語との連携やDLLの遅延バインディングのために使用する。
記述方法は、var(型推論)と似ているが、dynamicキーワードで宣言した変数の型は動的型になる。
var sx = 1; // int型
dynamic dx = 1; // dynamic型
C# 3.0以前のような静的型付け言語では、オブジェクトがどのような名前のプロパティやメソッドを持っているかをコンパイル時に知る必要がある。
以下の例では、'object' に 'X' の定義が含まれていません
というエラーが発生する。
static object GetX(object obj)
{
return obj.X;
}
C# 4.0以降では、dynamic型を使用することで、以下のように記述できる。
変数objがXというプロパティを持っているかは、プログラム実行時に調べる。
static dynamic GetX(dynamic obj)
{
return obj.X;
}
詳細を知りたい場合は、dynamicを参照すること。
オプション引数 / 名前付き引数
C# 4.0以降では、C++やVB.NET等に存在するオプション引数と名前付き引数が使用できる。
オプション引数
以下のように、規定値を持つメソッドを定義すると、引数の一部または全てを省略することができる。(オプション引数と呼ぶ)
この記法において、省略できるものは後の引数のみである。
static int Sum(int x = 0, int y = 0, int z = 0)
{
return x + y + z;
}
int s1 = Sum(); // Sum(0, 0, 0); と同じ
int s2 = Sum(1); // Sum(1, 0, 0); と同じ
int s3 = Sum(1, 2); // Sum(1, 2, 0); と同じ
名前付き引数
上記で定義した規定値を持つメソッドを、以下のような構文で呼ぶことができる。
名前付き引数は、引数の順番は自由に記述できる。
また、任意の箇所を省略することができる。
int s1 = Sum(x: 1, y: 2, z: 3); // Sum(1, 2, 3); と同じ
int s2 = Sum(y: 1, z: 2, x: 3); // Sum(3, 1, 2); と同じ
int s3 = Sum(y: 1); // Sum(0, 1, 0); と同じ
詳細を知りたい場合は、オプション引数・名前付き引数を参照すること。
ジェネリックの共変性と反変性
C# 4.0以降では、ジェネリクスの型引数に共変性と反変性を持つことができる。
ジェネリクスの共変性と反変性を実現するため、ジェネリクスの型引数に対して、in / outを指定する。
出力(戻り値またはプロパティのget)でのみ使用する場合は、型にoutを記述することで共変性が認められる。
public interface IEnumerable<out T> { ... }
IEnumerable<string> strings = new[] {"aa", "bb", "cc"};
IEnumerable<object> objs = strings;
// foreach (object x in strings) ってやっても問題ないんだから、
// objs に strings を代入しても OK。
入力(引数またはプロパティのset)でのみ使用する場合は、型にinを記述することで反変性が認められる。
public delegate void Action<in T> (T arg);
Action<object> objAction = x => { Console.Write(x); };
Action<string> strAction = objAction;
// objAction("string"); ってやっても問題ないんだから、
// strAction に objAction を代入しても OK。
詳細を知りたい場合は、ジェネリクスの共変性と反変性を参照すること。
COM相互運用時の特別処理
.NET FrameworkにはCOM相互運用機能があり、COMのクラスを.NET Frameworkのクラスであるかのように扱うことができる。
ただし、設計思想に大きな差があるので、.NET Frameworkでは不要だがCOM相互運用をする上では便利な機能がいくつか存在する。
C# 4.0以降では、COM相互運用のクラス(Runtime Callable Wrapper : .NET FrameworkからCOMを呼び出すためのラッパークラス)に対してのみ、
以下に示す特別な処理を行う。
- 引数の参照渡しにおいて、
ref
キーワードを付けなくても呼び出すことができる。- C#では、"引数の参照渡しは、呼び出し側からも参照渡しであることが一目で理解できる"ことが良いので、
ref
キーワードの省略は望ましくないが、 - COMの場合、参照渡しが不要と思われる引数も
ref
キーワードが付くので、ref
キーワードの省略を認めている。
- C#では、"引数の参照渡しは、呼び出し側からも参照渡しであることが一目で理解できる"ことが良いので、
get_X(index)
メソッド /set_X(index, value)
メソッドに対して、インデックス付きプロパティ構文(X[index]
という記述方法)が使用できる。- C#では、"インデックス付きプロパティではなく、インデクサ持ちの型のプロパティを作成する"という設計思想である。
- COMの全盛期では、インデックス付きプロパティが主流だったので、この構文も認められる。
- ただし、COMの
get_X(index)
をX[index]
で参照できるだけであり、C#において、インデックス付きプロパティが定義できるわけではない。 - また、VB.NETで記述したインデックス付きプロパティは、C#から呼ぶ場合は、
get_X(index)
/set_X(index, value)
という記述をする必要がある。