概要

え? 動的型付けは Python のことやろ? C# もできるんか? てかそれがジェネリック(どんな型でも引数にとれる)じゃないの? あれ? てか object 型は? やべ、ジェネリックと object との違いがわからなくなってきた。

 

流し読みノート

object と dynamic の違い

  • 動的型付けには dynamic 型を使う。 object と同じでほぼすべてのものへの参照を保持可能。違うのは、 object でとった引数は object にないメソッドやプロパティを使えないけど、 dynamic ならなんでもやりたい放題なところだ。ええい、全然うまく書けん。以下に実例を記す。
// ↓これはコンパイル不可。
//     object に Frobnicate なんてメソッドないからね。
public static object UseObjects(object a, object b)
{
    a.Frobnicate();
    return a + b;
}
// コンパイル可。
public static dynamic UseObjects(dynamic a, dynamic b)
{
    a.Frobnicate();  // たとえば int が渡されてきたら
                     // 当然 Frobinicate メソッドはないので
                     // RuntimeBinderException 発生。
                     // うん、 Python と一緒だね。
    return a + b;
}
  • ……いや、コンパイル可はわかるけどいいとこないやん。 C# のいいとこ死んでるじゃん。まあ↓のような型を定義すればエラー起こらないようにできるけど……。
pulbic class Frobnicatable
{
    public void Frobnicate() {}
    pulbic static Frobnicatable operator +(Frobnicatable left, Frobnicatable right)
    {
        return new Frobnicatable();
    }
}
// は? だったら dynamic で引数受けとらずに Frobnicatable でとればええやん。
  • ちなみに frobnicate って言葉は知らなかったんだけど、「いじくる」みたいな意味らしいよ。いじくるってのは tweak をよく使うけれど、とくに IT 関連で、物理的なものをいじくるときに使うみたい。 Stop frobnicating that switch!(スイッチをいじんのをやめろ)

 

なんで dynamic なんか追加したんや

  • Microsoft が dynamic を C# 4.0 から追加したのは、いくつかの相互運用のシナリオを単純にするため…… COM(Component Object Model)のサポートのためだ。
    • 何???
  • COM は .NET が出る前に多言語間開発をサポートしてたもの。 .NET が出たから役目はなくなってた。ただ Windows8 からまた COM ベースの API が提供されはじめた。
  • COM ベース API を扱う方法を COM オートメーションという。
  • COM オートメーションの利用者として有名なのは VBA(Visual Basic for Applications)。
  • なんかよくわからんけど、そのオートメーションとやらは動的な呼び出しに対応しているらしい。
  • ほんでなんかよくわからんけど、動的な呼び出しってのは、足りない引数を自動で供給することらしい。もう全然わからん。
  • 動的な言語では、これを自動で行うんだって。
  • でも C# はそれをしないから、たとえば Microsoft Word の16個の引数を受け取る Open メソッドを開くとき、不要なのに、いちいち16個の値を書かないといけなかったそうな。不要な引数が省略できないってこと。ハア?
  • dynamic キーワードははるかに優雅にそれを処理するそうな。ヘエ……。
  • まあそれでかじゃないようだけど、より優雅に、より洗練されたコードにするために導入されたものだってことよね。
  • dynamic 型はより自然に見えるコードを書けるように影で働くのです」「より自然な表現にできることと余計なものを減らすことが目的」。
    • dynamic の役割は COM と他の言語との相互運用の単純化であって、静的型付けのかわりに動的型付けプログラムを作ることではない。

最後だけ、ちょっとわかった。なにか、我々にはあんまり関係ないものを、隠れたところでキレイに処理するため機能なのだろう。 Python はシンプルな言語だけど、それは言語が裏で面倒なことを請け負ってくれているのだ。そういう類のハナシなのだろう。

なるほどねい。動的型付けである Python が型ヒントを取り入れたように、静的型付け言語も動的なものが欲しくなるときがあるってことかね。

 

dynamic は型であり型ではない

哲学かな?

  • C# では dynamic 型は特別な型として捉えられてるけれど、 CLR は dynamic を型として認識してない。実行時には object として扱う。
    • だから List<dynamic> は実際には List<object> になってる。
var x = new List<dynamic>();
Console.WriteLine(x.GetType() == typeof(List<object>));  // true になる。お前 object やないかい!

 

小休憩

たしかに、これは動的型付けだ。我々 Pythonista が慣れ親しんでいるものだ。だけど C# コードで目にすると、ただ静的型付けの魅力を損なっているだけに見えるな。「dynamic 型はより自然に見えるコードを書けるように影で働く」のならばずっと影に潜んでいたまえ。

やべ、ジェネリックと object との違いがわからなくなってきた。

ちなみに冒頭のこの疑問については……うーん、単純に、ジェネリックメソッドでは全部の引数が同じ型になるけど、 dynamic メソッドはその限りではない、くらいの納得でいいかな。

// a と b は違う型でも OK。
public static dynamic UseObjects(dynamic a, dynamic b)
// a と b は同じ型じゃないとダメ。
public static T UseObjects<T>(T a, T b)