C#っ!

1 12月

真面目に技術的な話を書くのは今日が初めてになりますね。初回ですし、C#という言語の歴史について改めて説明しましょう♪

C#誕生以前

C#誕生以前、J++という言語がありました。いわば、マイクロソフトによるJava独自拡張です。マイクロソフトが追加しようとしたのは:

  • COM(ネイティブ コード)相互運用
  • デリゲート(型安全、かつ、インスタンス メソッドにも対応可能な関数ポインター)

の2つです。

この拡張には、JVM(Java仮想マシン)にも手を入れる必要があり、マイクロソフト版のJVMでしか実行できませんでした。

この当時、Javaは「Write once, run anywhere」という目標を掲げていたため、SUNはマイクロソフトの独自拡張を良しとしませんでした。マイクロソフト版JVMは訴えられ、それまでWindowsに標準添付されていたJVMが外されました。

もしこのゴタゴタがなければ、C#は生まれなかったでしょう。

C# 1.0

JVMがダメなら自分でVMを作ればいいじゃない。

つまるところ、COM相互運用とデリゲートを持ったJavaとして生まれたのがC#です。

せっかく一度リセットしているので、その他にも以下のような機能が追加されています。

  • ユーザー定義の値型(struct)
  • プロパティ
  • 演算子のオーバーロード
  • 多次元配列
  • 属性
  • foreach

Java以外にも、DelphiやVisual Basicの影響を強く受けています。C++の機能のうち、Javaが除外しすぎた部分の復活もあります。

このうち、属性(アノテーション)とforeach(拡張for)は、後々Javaにも採用されましたね。

ユーザー定義の値型(struct)、多次元配列、属性辺りも、仮想マシン レベルでの対応が必要です。

C# 2.0

C# 1.0の正式版が搭載されたVisual Studioのリリースは2002年です。すでに前のバージョンのVisual Studio 6.0から、4年開いていました。通常、マイクロソフトの製品サイクルは2~3年なので、大きな挑戦だったことがわかります。

これ以上遅らせるわけにはいかず、C# 1.0は、J++とあまり変わらない言語としていったんリリースされます。そして、次のバージョンであるC# 2.0に回されたのが以下のような機能です。

  • ジェネリック
  • イテレーター ブロック

かなり初期から構想としてはあったようですが、スケジュール的な問題から2.0(2005年)まで待たされることになりました。

ジェネリックの追加は、Javaでも同時期に行っています。しかし、Javaが言語だけの修正でJVMに手を入れなかったのに対して、C#では、.NETの仮想マシン レベルでの対応をしています。型安全性と、パフォーマンスの向上(不要なキャスト、特にボクシングの回避)に貢献しています。

イテレーターは、さらにこの次(3.0)の大きな波、LINQへの前哨戦となっています。C# 1.0からあるforeachもそうですが、データ処理を行うコードを簡単にしようという一貫した目標があります。

この他、C# 2.0で、以下の機能も追加されています。

  • ヌル許容型
  • 静的クラス、部分クラス
  • 匿名メソッド

C# 3.0

基礎的な部分(1.0)やジェネリック(2.0)が落ち着いたところで、ようやく新しい一歩を踏み出します。他の言語を追う立場から、他の言語に追われる立場に変わったのがC# 3.0です。

C# 3.0のテーマはデータ処理。LINQ(Language Integrated Query)と呼ばれる、言語文法、ライブラリ、規約の整備が行われました。LINQと関連して、以下のような機能がC# 3.0に追加されています。

  • ラムダ式
  • 匿名型
  • 型推論
  • 拡張メソッド
  • オブジェクト初期化子

これらの機能は、LINQ以外の場面でも活躍します。

特に、ラムダ式はJavaでも次期バージョンでようやくサポートされそうです。

この他、C# 3.0で、以下の機能も追加されています。

  • 自動実装プロパティ
  • 部分メソッド

C# 4.0

C# 4.0のテーマは相互運用の強化です。

追加された機能としてはdynamic型ですが、これは、C#が動的になったということではなく、動的言語など、他の言語との連携を強めたということです。dynamic型の他にも、以下のような機能が追加されました。

  • オプション引数/名前付き引数
  • COM呼び出しに対するref省略

C# 3.0のラムダ式と同時に導入された、式ツリーを使った動的コード生成機能によって、.NET Framework上に動的言語を実装するのが簡単になりました。その結果、DLR(Dynamic Language Runtime)やIronPythonなどのプロジェクトが立ち上がっています。

C# 4.0のdynamic型は、このDLRの成果が一部使われていて、動的に生成したコードをキャッシュして、効率よく実行する仕組みを持っています。

相互運用の他、C# 4.0で、以下の機能も追加されています。

  • ジェネリックの共変・反変指定

C# future(5.0)

時代は非同期です。

嘘。非同期I/Oとか、Windows NTの時代からあるので、10数年は非同期の時代です。難しいとか、コードが見づらいという理由でみなが避けてきただけです。

CPUがマルチコア化してきたこの10年ほど、並列"計算"が重要なんて話もされますが、一番ヤバいのはI/O待ちです。I/O待ちでブロックしちゃダメです。たいていの人は、I/O待ちをブロックすることのコストを過少に見ています。

  • クライアント
    • 0.5秒フリーズしたらユーザーはストレスを感じます
    • I/O待ちはそのくらい余裕で超えます
  • サーバー
    • I/O待ちするだけのスレッドを立てると著しくパフォーマンスを落とします
    • 計算を並列化してもせいぜいコア数の分しかスピードアップしませんが、I/Oを非同期化すると2ケタくらい速くなったりします

時代は、簡単に書ける非同期I/Oです。

Before…

var c = new WebClient();
c.UploadStringCompleted += (sender, e) =>
{
    var html = e.Result;
    //
続きの処理
};
c.DownloadStringAsync(uri);

After!

var html = await c.DownloadStringTaskAsync(uri);
//
続きの処理

ということで、C# 5.0では非同期処理を、ブロックせずに待つ(一度完全にスレッドを解放した上で、非同期I/O完了後に続きの処理を再開する)ためのawait演算子が入ります。

時期的には、Windows 8に合わせてのリリースになりそうです。プレビュー版の時点でもう結構安定してるんですが、Windows 8につられてリリース時期が不透明に…

C# beyond future(6.0?)

5.0もまだプレビュー版なのに、すでにその次の話題も出ています。C# Compiler as a Service

要は、C#コンパイラーの内部構造をオープンにするということです。主に、Visual Studioの拡張を作りやすくなったり、C#をスクリプト言語としてアプリに組み込めるようになったりします。

というか、話自体はC# 3.0のころから脈々とあるものの、どう考えても非同期の方が優先なので、後回しになっています。その間に、スクリプト用途に関しては、monoに先を越されていたり

広告

コメント / トラックバック2件 to “C#っ!”

  1. 石坂忠広 2011/12/01 @ 17:28 #

    COM互換機能はMSのJVMから.NETに持ってこられたものと思います。だいたい.NETがではじめの頃MS自身がJ++のmsdn読めと言っていたぐらい。。。

Trackbacks/Pingbacks

  1. 新機能が入るまで « C#たんっ! - 2011/12/11

    […] まあ、結構大変なコードになりがちです。そこでC# 5.0。await演算子の出番です。初回に書いたコードですが、以下のように、同期処理と同じような構造で、非同期処理が書けます。 […]

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。