unsafeでも制限付き• class (参照型)はアドレス取れない•仮想メソッド テーブル(vtable)とか入ってるし• 親クラス側のレイアウト変更の影響受けるしclass Classvar c{fixedpublic int x;fixedpublic int y;fixed}ピン止め必須••= new Class();(void* p = &c) { }// error(void* p = &c.x) { } // OK(void* p = &c.y) { } // OK値型のメンバーのアドレスは取れるオブジェクト自体のアドレスは取れない
23.
unsafeでも制限付き• struct (値型)はアドレス取れる•ただし、メンバーが全部値型の時のみ• ↑「unmanaged型」と呼ぶstruct UnmanagedStruct{public int x;public int y;}メンバーが全部値型var uvoid*void*void*= new UnmanagedStruct();p1 = &u;// OKp2 = &u.x; // OKp3 = &u.y; // OK無制限にアドレス取れる
C++/CX• C++ ComponentExtensions• マイクロソフトのC++拡張素の標準C++コードC++/CXコンパイルC++内で完結して使う分にはオーバーヘッドなしCOMコードCOMを呼べる言語なら何からでも呼べるメタデータ(winmd).NETのメタデータと互換.NETから簡単に呼べる
とはいえ、いろいろ窮屈• genericsでは、インターフェイス制約かけないとメソッドすら呼べないstatic TypeMax<Type>(Type a, Type b){return a.CompareTo(b) > 0 ? a : b;}コンパイル エラーそんなメソッド知らない正しくはstatic Type Max<Type>(Type a, Type b)where Type : IComparableインターフェイス制約{return a.CompareTo(b) > 0 ? a : b;}IComparable.CompareTo
C++ 1y• C++にもジェネレーターが載るかも•C++ 17に向けて標準化案出てる• C++/CX向けの実装を元にMSが提案• async/awaitのついでsequence<int> range(int low, int high) resumable{for(int i = low; i <= high; ++i){yield i;}}
多重ディスパッチ• x, yの両方の型で動的に分岐•仮想メソッドでは(素直には)できないstatic class Extensions{public static string Dispatch(this Base x, Base y){動的な呼び出しreturn (string)X((dynamic)x, (dynamic)y);}static string X(A x, A y) { return "A - A"; }static string X(A x, B y) { return "A - B"; }static string X(Base x, Base y) { return "others"; }}
120.
多重ディスパッチ• 呼び出し例static voidMain(){Dispatch(new A(),Dispatch(new A(),Dispatch(new B(),Dispatch(new B(),}newnewnewnewA());B());B());A());////////A - AA - Bothersothersstatic void Dispatch(Base x, Base y){Console.WriteLine(x.Dispatch(y));}
121.
ダック タイピング• 静的な型に対してclassPoint{public int X { get; set; }public int Y { get; set; }public override string ToString(){return "Point(" + X + ", " + Y + ")";}}
122.
ダック タイピング• 同じ名前のメンバーを持つ別の型をまとめて処理staticclass Extensions{public static void CopyTo<T, U>(this T p, U q){dynamic x = p;dynamic y = q;y.X = x.X;X, Yを持つ任意y.Y = x.Y;の型に使える}}
123.
ダック タイピング• 呼び出し例varp = new Point();new { X = 10, Y = 20 }.CopyTo(p);Console.WriteLine(p);
124.
DLR連携• DLR (DynamicLanguage Runtime)• 例: IronPythonvar py = IronPython.Hosting.Python.CreateEngine();dynamic p = py.Execute("['a', 'b', 1, 2]");for (var i = 0; i < 4; i++)Console.WriteLine(p[i]);• DLRは内部的に.NETの型を生成してるので内部実装的にはこれも「静的な型に対する動的コード生成」
もう少し低レイヤーな話• Taskクラスasync Task<int>Method(){var x = await task1;var y = await task2;}_state = 1;if (!task1.IsCompleted){task1.ContinueWith(a);return;}case 1:var x = task1.Result;• スレッド機能だけあればいいわけじゃない• Task Pool、同期コンテキストとか
145.
スレッド• 非同期処理の最も低レイヤーな部分• ただし、高負荷for(int i = 0; i < 1000; i++){var t = new Thread(Worker);t.Start();}1000個の処理を同時実行• 細々と大量の処理(タスク)をこなすには向かない• 切り替え(コンテキスト スイッチ)のコストが高すぎる
C# 6.0 (予定)の例PrimaryConstructor / Property Expressionspublic class Point(int x, int y){public int X => x;immutableな型を作りやすくpublic int Y => y;}Declaration Expressions「式」で書けることの幅が広がるwhile ((var line = stream.ReadLine()) != null)line ...if ((var x = obj as Point) != null)x ...