The Future of C#のまとめ

The Future of C# | pdc2008 | Channel 9
VS2010がダウンロードできないので、不貞腐れてPDC2008のヘジたんセッションをまとめてみました。ヒアリングが壊滅的に苦手なので、あまり当てにならないと思います・・・(^^;

C#の進化

C#はマネージコードから始まってジェネリックLINQと進化してきた。

トレンド

  • Declarative
  • Dynamic
  • Concurrent

宣言型(Declarative)
LINQ関数型言語の要素を取り入れている。
命令型(Imperative)はHow(どのように)に重点を置いているが、
宣言型はWhat(何を)に重点を置いている。
ハードウェアの進歩により、HowをJIT等に任せられるようになるので「何を」がより重要になってくる。

静的(Static)と動的(Dynamic)
静的

  • 頑丈
  • ハイパフォーマンス
  • インテリジェンスなツールのサポート
  • より良いスケーリング

動的

並列(Cuncurrent)
マルチコアCPUの普及。言語やライブラリによるサポートの必要性。

共進化(Co-Evolution)
C#はマルチパラダイム言語(OOPやFPなど)として進化してきたが、
すべてをC#で賄うのではなく、他の言語が得意な分野はその言語に任せて、協調するのがベスト。

C#4.0 Dynamic Programming
C#4.0では動的プログラミングのサポートを強化する。これは先に述べた他言語との協調がポイントとなる。

C#4.0の新機能

  • 動的タイプ
  • 省略パラメータと名前付きパラメータ
  • COM相互運用の改善
  • 共変性と反変性

.NETにおける動的プログラミング
共通基盤としてのDLR。

  • Expression Trees
  • Dynamic Dispatch
  • Call Site Chaching

CLRは静的言語に対する共通基盤であったが、それを補完するようにDLRができた。

以降、C#4.0の新機能紹介。
動的タイプ

// 古き良き静的型プログラミング
Calculator calc = GetCalculator();
int sum = calc.Add(10, 20);

一方・・・

// COM or ruby or python ro javascript or ...
object calc = GetCalculartor();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add", new object[] {10, 20});
int sum = Converter.ToInt32(res);

これは大変。

// ScriptObjectなら
ScriptObject calc = GetCalculator();
object res = calc.Invoke("Add", 10, 20);
int sum = Converter.ToInt32(res);

ちょっと楽。

 // C# 4.0スタイル
 dynamic calc = GetCalculator();
 int sum = calc.Add(10, 20);

dynamicキーワードによりメソッドの動的呼び出し(実行時解決)&戻り値の自動変換。ワオ。

C#4.0で動的タイプをサポートしたが、静的タイプへの考えが変わったわけではない。
静的タイプは依然良いものである。動的タイプのサポートは協調すべき重要な動的言語(Javascript/ruby/python...)の増加によるものである。

省略可能&名前付きパラメータ

// 省略可能パラメータの例
public StreamReader OpenTextFile(
    string path,
    Encoding encoding = null,
    bool detectEncoding = true,
    int bufferSize = 1024);

// 名前付きパラメータ(呼び出し)
OpenTextFile("foo.txt", Encoding.UTF, bufferSize:4096);

注意 名前付きパラメータは最後に置く必要がある。

これらはVBとの相互運用のために導入したもので濫用は禁物。

COM相互運用の改善

object fileName = "Test.docx";
object missing = Sytem.Reflection.Missing.Value;
doc.SaveAs(ref fileName,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing);

大量のmissing・・・

C#4.0では、

doc.SaveAs("Test.docx");

これだけでOK。COM呼び出しにおけるrefパラメータは省略可能となる。

  • オートメーションオブジェクト -> dynamicへマッピング
  • 省略可能&名前付きパラメータによる相互運用性向上
  • 省略可能ref
  • No PIA

共変性と反変性
共変性の問題点。

string strings = GetStringArray(); // co-variant
Process(strings);

// Processメソッドの引数はobjectだが、渡せる
// しかし、objectsの実態はstringだが、メソッド内でButtonを代入
void Process(object[] objects) 
{
    objects[0] = "Hello"; // OK
    objects[1] = new Button(); // Exception!
}

反変性の問題点。

List<string> strings = GetStringList();
Process(strings); // コンパイルエラー!

// IEnumerable<T>は反変性なのでIEnumerable<string>は渡せない
void Process(IEnumerable<object> objects) {...}

しかし、IEnumerableは読み取り専用なので、渡せても問題はないはず・・・

そこで、

// out = Co-variant output positions only
public interface IEnumerable<out T> {}
public interface IEnumerator<out T> {}

outキーワードを付けることで共変性を表す。
これで、

List<string> strings = GetStringList();
Process(strings); // OK.

コンパイル出来る。

こちらは、反変性の指定。

// in 
public interface IComparer<in T>
{
    int Compare(T x, T y);
}

C#4.0の可変性のまとめ

  • インタフェースとデリゲートについてはサポートしていた
  • in/outキーワードによるチェックが可能
  • 値型に対しては常に反変性
  • ref/outパラメータは反変性となる


個人的な感想。
C#1.0が出た時に、P/Invokeとunsafeに代表されるようにWin32API/C/C++との相互運用をきっちり押さえていましたが、今回は広がりを見せているJavaScriptRubyPythonなどとの相互運用を強化してきて、ネイティブコード〜スクリプト言語まで結びつける強力な糊言語になりましたね。言語機能本体としては、痒いところに手を届かせた程度に思えますが、C#のポジション的には、もう、これくらいの機能強化で良いのかも知れませんね。