強い型付け(タイプセーフ)
C#言語は、基本的には強い型付け(または静的型付け)の言語とされています。これは、宣言される変数の型と、そこへ代入されるインスタンスの型は一致若しくは継承関係がある必要があるからです。
interface Car
{
void Drive();
}
class Bus : Car
{
public void Drive() => Console.WriteLine("Drive a bus");
}
class Bike
{
public void Drive() => Console.WriteLine("Drive a bike");
}
class Program
{
static void Main(string[] args)
{
// 左辺と右辺の型が一致
Bus bus1 = new Bus();
bus1.Drive();
// 左辺と右辺の型とに継承関係あり
Car bus2 = new Bus();
bus2.Drive();
// 左辺の型と右辺とは関係ないのでコンパイルが通らない
//Car bike = new Bike();
}
}
object
全ての型はobject型を直接または間接的に継承しています。つまり、すべての型はobject型と継承関係をもつため、object型への代入が可能と言えます。
とはいえ、object型に定義のないメンバーを使うにはキャストが必要になります。
構造体のような値型もobject型への代入が可能ですが、暗黙的にBoxingという処理が介在するのでパフォーマンスに影響があると言われてはいます。
// どんな型でもOK
object bus3 = new Bus();
// ただしメンバを使うにはキャストが必要
((Car)bus3).Drive();
// 数値型でも文字列型でもOK
object num1 = 1;
num1 = "1";
var(暗黙的型指定ローカル変数)
varは暗黙的型指定ローカル変数という邦訳が示す通り、暗黙的に型指定がなされるローカル変数です。 コンパイル時に型が決まるので、通常の型指定と同様に使えます。何の型でも入る訳ではありません。 VisualStudioのエディタで変数をポイントすると実際の型が表示されます。
// なんの型でもOK
var bike = new Bike();
// コンパイラによりこの時点で数値型(int)と推定されている。
var num2 = 2;
// なので以下のように数値型に文字列型は入らない。
//num2 = "2";
// 右辺から左辺の型が一目瞭然な場合
var reader = new System.IO.StreamReader();
// こういうのは可読性を阻害するので使わない方がよいとされる
var restlt = this.Execute(list);
// 型自身の名前が無い場合
var temp = list.First(o => {o.ID,o.Name});
dynamic
C#4.0以降で使用可能
これまでの変数がコンパイル時に型が決まる静的型付けであったのに対し、このdynamicはコンパイル時の型チェックが行われず、実行時に行われる。リフレクションの代替として使える。COMやPythonとのやり取りに便利。多用するものでもなし。
dynamic bus4 = new Bus();
bus4.Drive();
dynamic bike = new Bike();
bike.Drive();
// 以下のようなのもコンパイルは通る(実行時に例外発生)
bike.Fly();