SlideShare a Scribd company logo
1 of 216
C#や.NET Framework
がやっていること
第二版
岩永 信之
今日の内容
• C#や.NET Frameworkがやっていること
• どうしてそういう機能がある
• (自前で実装するなら)どうやればできる
• (自前でやる上で) 気を付ける必要がある点
注意
• ベースは3月にBoost勉強会でやった内容
• 通常の3倍速で1時間で話した
• 本来、1時間で話す内容じゃない
• かなりの前提知識を仮定
• 3時間話します
• いくつか追記
• 前提をだいぶ緩めたので背景説明など
• .NET vNextがらみ追加
• 5月の非同期勉強会での内容も少しマージ
同じような内容でも回数重ねてこなれてきてたり
目次
• 1時間目
• メモリ管理
• マルチ タスク管理
• 2時間目
• メタデータ
• 3時間目
• C#言語機能
1
2
3
1時間目
• メモリ管理
• ヒープ自動管理
• 境界チェック
• ドメイン分離
• マルチ タスク管理
• スレッドと非同期処理
1
2
3
“Managed”
• .NET FrameworkといえばManaged
• .NETがいろいろ管理
• メモリ リーク防止
• セキュリティ ホール防止
• v1リリース後、一番進歩が激しいのは非同期
• 効率的なタスク管理
• I/O-boundな非同期処理
Garbage Collection
メモリ リークをなくすために
メモリ管理(1)
• スタック
• 一番上に積む・一番上から取り出す
• ローカル変数用
• 管理は楽
• スコープがはっきりしてないと使えない
int x = 1;
int y = 2;
int z = 4;
int sum = x + y + z; 1 1
2
load 1 load 2
3
add
3
4
load 4
7
add
メモリ管理(2)
• ヒープ
• 連結リスト構造で任意の位置にメモリ確保
• 動的なメモリ利用できる
• 管理が大変
• 消し忘れ(メモリ リーク)があり得る
使用中かどうかのフラグ
☑□ □ ☑
次のヒープの位置
前のヒープの位置
… …
値型と参照型
• 値型
• intとかbyteとか
• structとかenumとか
スタック ヒープ
他の型
他の型
スタック上や、他の型の
中に直接埋め込まれる
• 参照型
• stringとか
• classとかdelegateとか
スタック ヒープ
スタック上や他の型の中
には参照情報だけある
ヒープ上に置かれる
ヒープ管理
• 怠ると
• 徐々にアプリが重くなる
• 長時間稼働させると突然の死
• その割に大変
• (自動管理がない頃)
プログラミングの苦労の半分くらい占める
• 本当にやりたいことに注力できてない
• 自動化したい
不要なオブジェクトの回収 =ゴミ を集め(garbage collection)
代表的な手法
• 参照カウント
• 生成・コピー代入のたびにカウントを +1
• 変数がスコープ外れるたびに -1
• カウントが0になったらメモリ削除
• Mark & Sweep
• ルート†からたどれるオブジェクトに印を付ける
• 印のついてないオブジェクトを削除
† スタックや静的フィールド中のオブジェクトなど
参照の起点となる場所
mark
sweep
Mark & Sweep
• ルートから参照をたどる
Mark
ヒープ
ルート
Sweep
使用中オブジェクト
未使用オブジェクト
Compaction
• GC時にオブジェクトの位置を移動
使用中オブジェクト
未使用オブジェクト
隙間をなくすように移動
後ろが丸ごと空くので次のメモリ確保が楽
Generation
• 移動したオブジェクトはしばらくノータッチ
Gen1 Gen0
Gen0
しばらくここは
ノータッチ
この範囲でだけ
メモリ確保・GC
オブジェクトの寿命
統計的に
• 短いものはとことん短く
• 長いものはとことん長い
一度GCかかったオブジェクト
はしばらく放置
.NET FrameworkのGC
• .NET FrameworkのGCはMark & Sweep
• Compactionあり
• 世代別 (3世代、Gen0~2)
• Backgroundスレッドで並列実行
Mark & Sweepと参照カウント
• 比較
• 一長一短ある
Mark & Sweep 参照カウント
メモリ確保 ○ 末尾を見るだけ × 空いている場所を探す
× カウント用の領域が追加
で必要
変数のコピー ○ ポインターのコピー × ポインターのコピーに加
え、参照数のカウント
アップ
メモリ解放 × MarkやCompactionに
時間がかかる
× 負担が1か所に集中
○ カウントが0になった時
にdeleteするだけ
× 循環参照が苦手
Throughput
• トータルの性能(throughput)はMark & Sweep
の方がいい
Mark & Sweep 参照カウント
メモリ確保 ○ 末尾を見るだけ × 空いている場所を探す
× カウント用の領域が追加
で必要
変数のコピー ○ ポインターのコピー × ポインターのコピーに加
え、参照数のカウント
アップ
メモリ解放 × MarkやCompactionに
時間がかかる
× 負担が1か所に集中
○ カウントが0になった時
にdeleteするだけ
× 循環参照が苦手
まとめてやる方がバラバラに
やるよりスループットはいい
頻度が高い操作なので
ここの負担が大きいと
全体の性能落ちる
特に、スレッド安全を求めるときつい
たかがインクリメントでも、atomic性
保証するとそこそこの負担
参照局所性も高くなって
キャッシュが効きやすい
短所の軽減
• 短所も、まったく打つ手がないわけじゃない
Mark & Sweep 参照カウント
メモリ確保 ○ 末尾を見るだけ × 空いている場所を探す
× カウント用の領域が追加
で必要
変数のコピー ○ ポインターのコピー × ポインターのコピーに加
え、参照数のカウント
アップ
メモリ解放 × MarkやCompactionに
時間がかかる
× 負担が1か所に集中
○ カウントが0になった時
にdeleteするだけ
× 循環参照が苦手
.NET 4以降、Background
スレッド実行してる
C++ 11的には
「move semantics活用
してね」
自前メモリ管理との混在
• スコープが短いならスタックにとればいいのに
• C#はclassは必ずヒープ、structはスタックになる
• 使い分けれない
• Mark & Sweep管理領域内のポインターを管理
外に渡すときには注意が必要
• Compactionでメモリ移動しないように
「ピン止め」が必要
• 結構ガベージ コレクションのパフォーマンス落とす
おまけ: 他の言語
• C++: 主に参照カウント方式のライブラリ利用
• 型がはっきりしない言語ではMark & Sweepしにくい
• できなくはないけども「保守的」になる(効率落とす)
• 数値を無差別にポインター扱いしてMarkする
• Pythonとか: 参照カウントとMark & Sweepの併用
• ○ 循環参照問題避けつつ、負担を1か所に集中させない
• × 性能的には悪いとこどり
• Go: 割当先を自動判別
• スコープ内で完結してたらスタックに、さもなくばヒープに
• これはこれでスタックの浪費激しそうなんだけども…
• なので、可変長スタック持ってる
注意: GCあってもリーク
• 長時間生きているオブジェクト†が参照持った
ままになると、GC対象になれない
† ワーストケースはアプリ稼働中ずっと生きているオブジェクト
class View : UserControl
{
public View(Model model)
{
model.PropertyChanged += (sender, e) =>
{
// データの表示を更新
};
}
}
よく起こり得る例
ビューは画面遷移で消える
モデルはずっと生きてる
イベント購読で、
モデルがビューの参照持つ
解除 (-=) しないとメモリ リーク
ポイント
• メモリ管理は大変なので自動化
• Mark & Sweep
• いろいろ賢いアルゴリズム搭載してるし、ほとんど
の場合、任せた方がいい
• GCあってもメモリ リークは起こり得るので注
意
境界チェック
意図しないメモリ領域にはアクセスさせない
配列の境界チェック
• .NETの配列は厳しい
• 常に境界チェックしてる
• 要はbuffer overrun†防止
• ちなみにJIT最適化で不要な境界チェック消してる
(明らかに境界を侵さないものはチェック不要)
• for (var i; i < a.Length; ++i) とか
• foreach (var item in a) とか
配列 a
OutOfRange OutOfRange
a[-1] a[length+1]
† クラッシュやセキュリティ ホールの温床
unsafe
• とはいえ、C#にもポインターあるんだけども
var x = new[] { 1, 2, 3, 4, 5 };
unsafe
{
fixed(int* px = &x[0])
{
Console.WriteLine(px[100]);
}
}
メモリ移動の防止
(ピン止め)
範囲チェックなし
安全でないコード
この中でだけポイ
ンター利用可能
buffer overrunやりたい放題
unsafeでも制限付き
• class (参照型)はアドレス取れない
• 仮想メソッド テーブル(vtable)とか入ってるし
• 親クラス側のレイアウト変更の影響受けるし
class Class
{
public int x;
public int y;
}
var c = new Class();
fixed (void* p = &c) { } // error
fixed (void* p = &c.x) { } // OK
fixed (void* p = &c.y) { } // OK
ピン止め必須
• 値型のメンバーのアドレスは取れる
• オブジェクト自体のアドレスは取れ
ない
unsafeでも制限付き
• struct (値型)はアドレス取れる
• ただし、メンバーが全部値型の時のみ†
• ↑「unmanaged型」と呼ぶ
struct UnmanagedStruct
{
public int x;
public int y;
}
var u = new UnmanagedStruct();
void* p1 = &u; // OK
void* p2 = &u.x; // OK
void* p3 = &u.y; // OK
メンバーが
全部値型
無制限にアドレス取れる
† 正確には、再帰的に全子要素が値型、かつ、型パラメーターも値型
unsafeでも制限付き
• struct (値型)であっても制限付き
• メンバーに1つでも参照型を含むとダメ
• ↑「managed型」と呼ぶ
struct ManagedStruct
{
public int x;
public string y;
}
var u = new ManagedStruct();
void* p1 = &u; // error
void* p2 = &u.x; // OK
void* p3 = &u.y; // error
メンバーに
参照型が1つ
本体のアドレス取れない
値型のメンバーのところ
だけはアドレス取れる
ポイント
• unsafe
• 危険なことは基本認めない
• 面倒な追加の構文を要求
• コンパイル オプションでも/unsafeの明記必須
• fixed
• ガベージ コレクションとの兼ね合い
• Compaction阻害になるので注意
• 「Unmanaged型」に限る
• 実装依存な部分(vtableとか)や、
型の定義側の変更が利用側に極力影響しないように
AppDomain
実行環境の分離
セキュリティ保証
コンポーネントの連携
• 他のアプリの機能を自分のアプリから呼びたい
• WordとかExcelとかのドキュメントを出力
• サーバー上に自分のアプリを配置したい
• IIS上に(ASP.NET)
• SQL Server上に
• (必ずしも)信用できない
• セキュリティ保証
• 参照先のクラッシュにアプリ/サーバー
が巻き込まれないように
• コンポーネントのバージョン アップ
AppDomain
• 単一プロセス内で、分離された複数の実行領域
(domain)を提供
• 「分離」
• plugin: 動的なロード/アンロード
• security: AppDomainごとに異なる権限付与
• isolation: 別メモリ空間
AppDomain 1
AppDomain 2…
プロセス
必ずしも信用できないコードを
安全に、動的に呼び出し
ドメイン間には壁がある
• 別メモリ空間に分離されてる
AppDomain 1 AppDomain 2
互いに独立
ドメイン間の通信
• マーシャリング(marshaling)
• marshal (司令官、案内係)の命令通りにしか壁を超
えれない
AppDomain 1 AppDomain 2
• 司令がダメといったら通れない
• 司令の指示通りの形式にいったん
シリアライズしないといけない
AppDomain 1 AppDomain 2
ドメイン間の通信
• ダメな例
これをBに渡し
たいとして
あるオブジェクト
AppDomain 1 AppDomain 2
ドメイン間の通信
• ダメな例
shallow copyなんてしようもんなら
A側のメモリへの参照が残る
AppDomain 1 AppDomain 2
ドメイン間の通信
• よい例
serialize deserialize
{
{1, 2},
{3, 4},
{5, 6}
}
この辺りがマーシャリング
一度シリアライズ 必ずdeep copy
.NETのマーシャリング
• 2種類
• marshal by ref
• 参照を渡すんだけど、メモリ領域は直接触れない
• メソッド越しにしか操作しちゃいけない
• 「このメソッドを呼んでくれ」っていうメッセージだけ
がドメインを超えてわたって、実際の実行は相手側ドメ
インで(プロキシ実行)
• marshal by value
• 値をシリアライズして相手側に渡す
• 規定では、BinarySeralizerを使用
privateフィールドまで含めてリフレクションで
内部状態を取得してシリアライズ
.NETのマーシャリング(文字列)
• 文字列は特殊扱い
(文字コード変換が不要な場合)
• marshal by valueみたいにシリアライズを経ない
• marshal by referenceみたいにプロキシ実行しない
• 参照を渡して、メモリを直接読んでもらう
• immutableかつrange-check付きに作ってある
• 変更不可なので参照を渡しても安全
• COM (ネイティブ)に対して文字列を渡す時すらこの方式
AppDomain 1 AppDomain 2
その他のコスト
• マーシャリング以外にもいくらかコストが
• 例えばライブラリの読み込み
Library X Library X
別ドメインに全く同じライブラリを読み込んでも、
それぞれ別イメージが作られる
Global Assembly Cache (GAC)にあるDLLだけは別
GAC中のは同じメモリ イメージが共有される
おまけ: 他の言語
• COMなんかはマーシャリングやってる
• というか「COMの頃から」やってる
• .NETの前身なので
• さもなくば、プロセス分離してプロセス間通信
• OS特権がないと他プロセスのメモリにはアクセス
できない
• 安全だけどかなり高負荷
• RPC†とか一時期流行ったけども廃れた
† ただの関数呼び出しに見えるコードで、内部的にプロセス間通信する
知らないうちに性能落とすとか、リモート側でのエラーが処理しにくいとか
ポイント
• プラグインとかやるなら「分離」が必須
• とはいえ、プロセス分けると負担が大きすぎる
• プロセス内で分離を保証する仕組み
• AppDomain
• マーシャリング
• それなりにコストがかかるけども、セキュリティに
は変えられない
スレッド
応答性のよいプログラムを書くために
OSやアプリ全体をフリーズさせないために
マルチタスク
• コンピューター内で複数のタスクが同時に動作
• CPUコア数に制限されない
タスク1 タスク2 タスク3 …
タスクの動作期間
実際にCPUを使って
動いている期間
1つのCPUコアを複数の
タスクがシェアしてる
問題は
• どうやって他のタスクにCPUを譲るか
• 誰がどうスケジューリングするか
2種類のマルチタスク
† preemptive: 専買権を持つ、横取りする
※cooperative
• ハードウェア タイマーを使って強制割り込み
• OSが特権的にスレッド切り替えを行う
• ○利点: 公平 (どんなタスクも等しくOSに制御奪われる)
• ×欠点: 高負荷 (切り替えコストと使用リソース量が多い)
プリエンプティブ†
• 各タスクが責任を持って終了する
• 1つのタスクが終わるまで次のタスクは始まらない
• ○利点: 低負荷
• ×欠点: 不公平 (1タスクの裏切りが、全体をフリーズさせる)
協調的※
なのでスレッドはこっち
これが致命的
ただ、問題はこれ
問題: スレッドは高コスト†
• 細々としたタスクを大量にこなすには向かない
for (int i = 0; i < 1000; i++)
{
var t = new Thread(Worker);
t.Start();
}
大量の処理をスレッド実行
リソース消費大
切り替え頻発
…
† スレッドごとに数MBのメモリを確保したり
スレッド切り替えにOS特権が必要だったり
文脈が切り替わっちゃうのでキャッシュ ミスしたり
解決策: スレッド プール
• スレッドを可能な限り使いまわす仕組み
• プリエンプティブなスレッド数本の上に
• 協調的なタスク キューを用意
スレッド プール
キュー
タスク1
タスク2
…
数本※のスレッ
ドだけ用意
空いているスレッドを探して実行
(長時間空かない時だけ新規スレッド作成)
新規タスク
タスクは一度
キューに溜める
※ 理想的にはCPUのコア数分だけ
スレッド プールの性能向上
• Work Stealing Queue
• lock-free実装†なローカル キュー
• できる限りスレッド切り替えが起きない作り
ローカル
キュー1
ローカル
キュー2
スレッド1 スレッド2
グローバル
キュー
①
スレッドごとに
キューを持つ
まず自分用の
キューからタスク実行
②
ローカル キュー
が空のとき、
他のスレッドから
タスクを奪取
† 今回は詳細割愛
スレッド プールの性能向上
• Work Stealing Queue
• lock-free実装†なローカル キュー
• できる限りスレッド切り替えが起きない作り
ローカル
キュー1
ローカル
キュー2
スレッド1 スレッド2
グローバル
キュー
①
スレッドごとに
キューを持つ
まず自分用の
キューからタスク実行
②
ローカル キュー
が空のとき、
他のスレッドから
タスクを奪取
ポイント
• スレッドは高コスト
• Threadクラスはこっち
• スレッド プールの利用推奨
• Taskクラスはこっち
† 今回は詳細割愛
問題: CPUの外の世界は遅い
• 実行速度が全然違う
ALU
メイン・メモリ
CPU 周辺機器
数千~
下手すると数万、数億倍遅い
>>>
2種類の負荷
• CPU-bound (CPUが性能を縛る)
• マルチコアCPUの性能を最大限引き出したい
• UIスレッドを止めたくない
• I/O-bound (I/O※が性能を縛る)
• ハードウェア割り込み待つだけ
• CPUは使わない
• スレッドも必要ない
※ Input/Output: 外部ハードウェアとのやり取り(入出力)
I/O完了待ち
• I/O-boundな処理にスレッドは不要
あるスレッド
要求
応答
この間何もしないのに
スレッドを確保し続け
るのはもったいない
解決策: I/O完了ポート※
• スレッドを確保せずI/Oを待つ仕組み
• コールバックを登録して、割り込みを待つ
• コールバック処理はスレッド プールで
スレッド プール
タスク1
タスク2
…
※ I/O completion port
あるスレッドアプリ
I/O完了ポート
ハードウェア
I/O開始 I/O完了
コールバック
登録
コールバック登録後、
すぐにスレッド上での
処理を終了
割り込み信号
I/O完了ポート※
• スレッドを確保せずI/Oを待つ仕組み
• コールバックを登録して、割り込みを待つ
• コールバック処理はスレッド プールで
スレッド プール
タスク1
タスク2
…
※ I/O completion port
あるスレッドアプリ
I/O完了ポート
ハードウェア
I/O開始 I/O完了
コールバック
登録
コールバック登録後、
すぐにスレッド上での
処理を終了
割り込み信号
ポイント
• I/O-boundな処理にスレッドを使っちゃダメ
• I/O用の非同期メソッドが用意されてる
(内部的にI/O完了ポートを利用)
問題: スレッド安全保証
• スレッド安全なコードは高コスト
• いっそ、単一スレッド動作を前提に
• メッセージ ポンプ
MSG msg;
while (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} こんな感じのループが単一スレッドで動作
他のスレッドからメッセージを
キュー越しに受け取って処理
典型例: UIスレッド
• GUIはシングル スレッド動作(UIスレッド)†
• ユーザーからの入力受け付け
• 画面の更新
UIスレッド
ユーザー
からの入力
OK
グラフィック
更新
他のスレッド
処理中は
応答不可
他のスレッドから
は更新不可
† C#/.NETに限らず、だいたいの言語・環境でGUIはシングル スレッド動作
矛盾
単一スレッドからしか
UI更新できない
そのスレッドを止める
とUIフリーズ
シングル スレッド推奨
マルチ スレッド推奨
OK
解決策: メッセージ配送
1. スレッド プールで重たい処理
2. UIスレッドに処理を戻してからUI更新
UIスレッド
OK
更新
他のスレッド
重たい処理
Dispatcher.Invoke
Task.Run
※ dispatcher: 配送者
渡す役割を担うのが
ディスパッチャー※
他のGUIフレームワークだとevent queueとかhandlerとかいう
名前で提供されたりするものの、やってることは一緒
いったんUIスレッド
にメッセージを渡す
おまけ: 他の言語
• スクリプト言語の類はだいたいスレッド機能
持ってない
• GUIを前提にしていないか
• GUIがフリーズするほどの処理を書くことを前提に
していないか
• C++とかは最近(11で)ようやく標準化
• それまでは、スレッドは結構環境依存
ポイント
• 応答性と全体のパフォーマンスとの兼ね合い
• スレッド プール
• I/O待ちのためにスレッドは使っちゃダメ
• I/O完了ポート
• スレッド安全保証はそれなりに高コスト
• シングル スレッドでメッセージ ポンプ
• メッセージ配送
Task
クラス
2時間目
• メタデータ
• 動的リンク
• JIT
• PCL
1
2
3
メタデータとは
• 実行可能ファイル中には本来不要なデータ
• プログラムを作るためのデータ
• 実行に必要なデータよりもメタ(高次)
var x = p.X;
var y = p.Y;
var z = p.Z;
var pp = (byte*)&p;
var x = *((int*)pp);
var y = *((int*)(pp + 4));
var z = *((int*)(pp + 8));
プロパティ名とか
単にプログラムを動かすだけなら
相対アドレスだけわかればいい
.NETでは、こういうメタデータを実行可能ファイルに残す
.NETのメタデータ
• .NETのメタデータ(≒ 型情報)
• DLLにどういう型が含まれるか
• どういう型がどういうメンバーを持っているか
• 外部のどういうDLLを参照しているか
• バージョン情報
• DLLにメタデータを残すことで
• プログラミング言語をまたげる
• 動的リンクでのバージョン管理ができる
おまけ: 昔と今
• COMの頃
• メタデータを自分で書いてた
(自動化するツールあるけど)
• .tlb/.olbファイル
• .NET Framework
• .NET自体がメタデータの規格を持ってる
• C#とかをコンパイルするだけで作られる
おまけ: C++/CX
• C++ Component Extensions
• マイクロソフトのC++拡張
C++/CX
素の標準
C++コード
COMコード
メタデータ
(winmd)
コンパイル
C++内で完結して使う分
にはオーバーヘッドなし
COMを呼べる言語なら
何からでも呼べる
.NETのメタデータと互換
.NETから簡単に呼べる
動的リンク
実行可能ファイルにメタデータが含まれていることで
ライブラリ共有
• 前提: ライブラリは共有する
アプリA
アプリB
ライブラリX
ライブラリY
version 1
version 1
動的リンク
• ライブラリ単体での差し替え
• セキュリティ ホールや、致命的なバグの修正
アプリA
アプリB
ライブラリX
ライブラリY
version 2
version 1
更新不要
差し替え
アプリ実行時にライブラリをリンクしなおしてる = 動的リンク
いまどきの事情
• ライブラリはアプリのパッケージに同梱
• 動的なリンクいるの?
アプリA ライブラリX
ライブラリY アプリB
ライブラリX
ライブラリY
アプリAパッケージ アプリBパッケージ
別バイナリ・別々に配布
別バージョンでも困らない
とはいえ…
差分ダウンロード
※ Windowsストア アプリはこういう仕組み持ってる
アプリA ライブラリX
ライブラリY
アプリAパッケージ version 1
version 1
アプリA ライブラリX
ライブラリY
アプリAパッケージ version 2
version 2
version 1 version 1
version 1 version 1
ライブラリX
差分
version 2
ダウンロード
アプリA ver.1
インストール機
バージョンアップ時
更新
ここだけ新しい
アプリB
ライブラリX
ライブラリY
アプリ間でライブラリ共有
※ Windowsストア アプリはこういう仕組み持って
アプリA ライブラリX
ライブラリY
アプリAパッケージ
ライブラリY
アプリBパッケージ
差分
アプリA
インストール機アプリB
アプリBインストール時
X、Yは同じものを共有
(ハード リンク作るだけ)
version 1
version 1 version 1
version 1
同じバージョン
パッケージ管理
※ ASP.NET vNextはこういう仕組み持ってる
開発機 アプリ サーバー パッケージ リポジトリ
例
http://nuget.org
http://myget.org
project.json
*.cs
"dependencies": {
"Library.A": "",
"Library.B": ""
}
var c = new Configuration();
c.AddJsonFile("config.json");
a.UseServices(services => …);
ソースコードだけを
アップロード
サーバー上で
編集可能
ライブラリの不足・更新
はクラウドから取得
ポイント
• 動的にリンク
• 部分更新・差分ダウンロード
• ライブラリ共有
• パッケージ管理
• リンクに必要な情報(メタデータ)を実行可能
ファイルに残す
• メタデータも規格化されてる
• C#/.NETの場合はコンパイルするだけで作られる
JIT
(Just-in-Time compile)
実際の動的リンクの挙動
中間コードとJITコンパイル
• .NET Frameworkの中間言語
• 高級言語のコンパイラーを作る人と、CPUごとの最
適化する人の分業化
• セキュリティ チェックしやすくなったり
• 動的リンク時に、コード修正の影響をJITで吸収
高級言語
(C#など)
中間言語
(IL)
ネイティブ
コード
ビルド時に
コンパイル
Just-in-Time
コンパイル
JITである必要ない
LLVMとかでも中間言語介してコンパイルしてる
ストア審査ではじくとか他にも手段はある
例
• (C#で)こんな型があったとして
• 整数のフィールドを3つ持つ
public struct Point
{
public int X;
public int Y;
public int Z;
}
例
• こんなメソッドを書いたとする
• フィールドの掛け算
static int GetVolume(Point p)
{
return p.X * p.Y * p.Z;
}
IL
• C#コンパイル結果のIL
.method private hidebysig static int32
GetVolue(valuetype Point p) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Point::X
IL_0006: ldarg.0
IL_0007: ldfld int32 Point::Y
IL_000c: mul
IL_000d: ldarg.0
IL_000e: ldfld int32 Point::Z
IL_0013: mul
IL_0014: ret
}
型とかフィールド
の名前がそのまま
残ってる
型情報
メタデータ
ネイティブ コード
• JIT結果 (x64の場合)
push ebp
mov ebp,esp
cmp dword ptr ds:[5011058h],0
je 00FE2A01
call 74B7AEA8
mov eax,dword ptr [ebp+8]
lea edx,[ebp+8]
imul eax,dword ptr [edx+4]
lea edx,[ebp+8]
imul eax,dword ptr [edx+8]
pop ebp
ret 0Ch
4とか8とかの数値に
型情報は残らない
メモリ レイアウト
• この4とか8の意味
public struct Point
{
public int X;
public int Y;
public int Z;
}
Point
X
Y
Z
4バイト
8バイト
※レイアウトがどうなるかは環境依存
メモリ レイアウト
• この4とか8の意味
public struct Point
{
public int X;
public int Y;
public int Z;
}
Point
X
Y
Z
4バイト
8バイト
※レイアウトがどうなるかは環境依存
ILの時点までは名前
で参照してる
ネイティブ コードは
レイアウトを見て
数値で参照してる
数値でのフィールド参照
• C#で擬似的に書くと
static int GetVolume(Point p)
{
return p.X * p.Y * p.Z;
}
var pp = (byte*)&p;
var x = *((int*)pp);
var y = *((int*)(pp + 4));
var z = *((int*)(pp + 8));
return x * y * z;
4とか8とかの数値に
※これ、一応C#として有効なコード(unsafe)
変更してみる
• 大して影響しなさそうな
ほんの些細な変更をしてみる
public struct Point
{
public int X;
public int Y;
public int Z;
}
public struct Point
{
public int X;
public int Z;
public int Y;
}
フィールドの順序変更
その結果起きること
• メモリ レイアウトが変わる※
Point
X
Y
Z
Point
X
Z
Y
※ この例(フィールド変更)以外でも、仮想メソッド テーブル
とかいろいろレイアウトが変わるものがある
ILレベルでの影響
• 影響なし
IL_0000: ldarg.0
IL_0001: ldfld int32 Point::X
IL_0006: ldarg.0
IL_0007: ldfld int32 Point::Y
IL_000c: mul
IL_000d: ldarg.0
IL_000e: ldfld int32 Point::Z
IL_0013: mul
IL_0014: ret
名前で参照してるん
だから特に影響ない
JITが吸収してくれる
ネイティブ レベルでの影響
• ここで影響が出る
push ebp
mov ebp,esp
cmp dword ptr ds:[5011058h],0
je 00FE2A01
call 74B7AEA8
mov eax,dword ptr [ebp+8]
lea edx,[ebp+8]
imul eax,dword ptr [edx+4]
lea edx,[ebp+8]
imul eax,dword ptr [edx+8]
pop ebp
ret 0Ch
8
4
更新が必要
利用側の再コンパイルが必要
ライブラリ側だけの差し替えじゃダメ
ただし…
• この役割に焦点を当てるなら…
• 毎回毎回JITする必要ない
• 全部が全部ILな必要ない
Ngen
• Ngen.exe
• Native Image Generator
• ILを事前にネイティブ化するためのツール
• 自前管理が必要
• アプリのインストーラー※とかを作って明示的に呼び出し
• 参照しているライブラリが更新された時には呼びなおす
必要あり
• かなり面倒なのでアプリを
Ngenすることはめったにない
• .NET自体が標準ライブラリの
高速化のために使ってる
※ 要するに、JITの負担を起動時じゃなくてインストール時に前倒しする
Auto-Ngen
• .NET Framework 4.5以降なら
• NgenがWindowsサービスとして常に動いてる
• アイドル時に動作
• 利用頻度の高いものを自動的にNgen
• デスクトップ アプリの場合はGACアセンブリのみ
• Windowsストア アプリの場合はすべてのアセンブリ
• よく使うアプリの起動はだいぶ早くなる
• インストール直後の起動は相変わらず遅い
MDIL (ネイティブのおさらい)
• おさらい: ネイティブ コードだと
push ebp
mov ebp,esp
cmp dword ptr ds:[5011058h],0
je 00FE2A01
call 74B7AEA8
mov eax,dword ptr [ebp+8]
lea edx,[ebp+8]
imul eax,dword ptr [edx+4]
lea edx,[ebp+8]
imul eax,dword ptr [edx+8]
pop ebp
ret 0Ch
参照しているライブラリ
のレイアウトが変わった
時に再コンパイルが必要
MDIL (部分的にネイティブ化)
• じゃあ、こんな形式があればいいんじゃ?
push ebp
mov ebp,esp
cmp dword ptr ds:[5011058h],0
je 00FE2A01
call 74B7AEA8
mov eax,dword ptr [ebp+8]
lea edx,[ebp+8]
imul eax,dword ptr [edx+4]
lea edx,[ebp+8]
imul eax,dword ptr [edx+8]
pop ebp
ret 0Ch
int32 Point::X
int32 Point::Y
int32 Point::Z
ほぼネイティブ レイアウトのところ
だけ抽象的に型情報
を残しておく
MDIL: Machine Dependent Intermediate Language
MDIL (Compile in the Cloud)
• ストア サーバー上でMDIL化までやっておく
C#コード
IL
MDIL
ネイティブ コード
C#コンパイラー
MDILコンパイラー
リンカー
開発環境でILにコンパイル
Windowsストア サーバー
上でILをMDIL化
Windows Phone実機上では
レイアウトの解決(リンク)だけ行う
インストール直後の起動も高速
※ Windows Phoneアプリはこういう仕組み持ってる
ポイント
• JITの主な利点
• 動的リンクしやすい
• (後述の、動的コード生成しやすいとかもある)
• ただし、常にJust-In-Timeな必要ない
• インストール時 → Ngen
• サービスで定期的に → Auto-Ngen
• ストア サーバー上で → Compile in the Cloud
vNextはJITだけじゃない
• (詳細は後述)
選べる実行形態
• 事前に完全ネイティブ化 → .NET Native
• ソースコード配置 → Cloud Mode
リフレクション
動的コード生成
メタデータ利用
• メタデータ(プログラム生成に必要な情報)を
持っているということは
• 動的にプログラム コードを生成できる
• 自己反映的動作(リフレクション)
コード生成API
高級言語
(C#)
構文木
IL
ネイティブ
コード
parse
emit
JIT
.NET Compiler Service†
式ツリー
(System.Linq.Expressions)
ILGenerator
† 旧称(コードネーム)Roslyn
動的なコンパイルが可能
C#コードから
• .NET Compiler Serviceの例
session.Execute<Func<Point, int>>("p => p.X * p.Y * p.Z")
C#ソースコードをコンパイル
C#→[parse]→構文木→[emit]→IL→[JIT]→Native
構文木から
• System.Linq.Expressions
Expression.Lambda<Func<Point, int>>(
Expression.Multiply(
Expression.Multiply(
Expression.Field(p, x),
Expression.Field(p, y)),
Expression.Field(p, z)),
ILを直接生成
• ILGenerator
var gen = m.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, x);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, y);
gen.Emit(OpCodes.Mul);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, z);
gen.Emit(OpCodes.Mul);
gen.Emit(OpCodes.Ret);
コード生成にかかる時間
• 本当はあんまり動的にやりたくない
• 当たり前だけどparseは遅い
• なので、.NETはソースコード配布じゃなくてIL配布
• できる限りコンパイル時生成したい
かかった時間[ミリ秒]
ILGenerator
(JIT)
39.89
Expressions
(emit→JIT)
67.94
Compiler Service
(parse→emit→JIT)
4314
倍遅い
2桁遅い
ある環境で、あるコードの生成結果の例
ポイント
• メタデータを持ってる = 動的コード生成でき
る
• C#ソースコードから: .NET Compiler Service
• 式ツリーから: System.Linq.Expressions
• IL直接生成: ILGenerator
遅い・楽
速い・面倒
※ .NET Native(後述)だと動的コード実行が
インタープリター方式になっちゃって
かなり遅いので注意
vNext
JIT以外の実行方法
.NET vNext
• .NET Native
• Cloude Mode
JITは便利なんだけど
利点
• 動的リンク・部分更新しやすい
• セキュリティ検証しやすい
• (ソースコード配布よりは)高速
欠点
• .NET Frameworkのランタイム インストール必須
• (ネイティブ配布よりは)低速
• (ソースコード配布よりは)デバッグ・修正が面倒
用途によっては…
例えば携帯デバイス向け
利点
• 動的リンク・部分更新しやすい
• セキュリティ検証しやすい
• (ソースコード配布よりは)高速
欠点
• .NET Frameworkのランタイム インストール必須
• (ネイティブ配布よりは)低速
• (ソースコード配布よりは)デバッグ・修正が面倒
ストア サーバー上で
やればいい
ランタイム分のストレージ
容量使いたくない
性能的に結構困る
ストア サーバー上で
ネイティブ化
.NET Native
.NET Native: 事前ネイティブ化
• .NETアプリを事前にネイティブ化
• 実用上はストア サーバー上でネイティブ化
• セキュリティ保証
• アップロード時にはIL
• 審査付き
• クライアント デバイス的には低コスト
• JITのコストなし
• ランタイムのインストール不要
• Visual Studio上で直接ネイティブ化も可能
• 通常版の.NETとの差で問題が起きないかの確認
• パフォーマンスの確認
.NET Native: 最適化
• 「事前にJIT相当の処理」以上の最適化も
• シリアライズなどのコードを事前に展開
• 型情報を見たいからリフレクションを使ってただけで、
実際にはビルド時に型が確定してることが多い
• 必要な分だけ静的リンク
• ライブラリをまたいだ最適化が可能
• 不要コードは残さないので実行可能ファイルのサイズは
膨らまない
.NET Native: リフレクション
• リフレクションも使える
ただし…
• XAML {Binding}など、推論が効く部分は自動判定し
てくれる
• それ以外は、自分で「この型はリフレクションで
使ってる」という情報を書かないとダメ
(Runtime Directiveファイル)
• 動的コード生成は無理
• 式ツリーなどはインタープリター方式になるので遅い
例えばサーバー向け
利点
• 動的リンク・部分更新しやすい
• セキュリティ検証しやすい
• (ソースコード配布よりは)高速
欠点
• .NET Frameworkのランタイム インストール必須
• (ネイティブ配布よりは)低速
• (ソースコード配布よりは)デバッグ・修正が面倒
アプリ稼働時間が長くて、
最初の1回だけのコストは
無視できる(低速でもいい)
開発機とサーバー機でバー
ジョンが違って困ることが
サーバー上で確認しつつ
その場でソースコードを修正したい
ソースコード配置
自動パッケージ管理
Cloud Mode
アプリごとに別バー
ジョンを使えない
Cloud Mode:
• ソースコード配置
• .NET Compiler Service (Roslyn)を利用
• メモリ上で全部コンパイル(一時ファイルを残さない)
• ソースコード書き替えて、ブラウザー更新するだけ
• side-by-sideインストール
• (サーバーにインストールするんじゃなく)
アプリごとに別.NETランタイムを使える
• アプリごとにバージョンを変えれる
• 開発時と同じバージョンを使える
Cloud Mode: パッケージ管理
• 自動パッケージ管理
開発機 アプリ サーバー パッケージ リポジトリ
例
http://nuget.org
http://myget.org
project.json
*.cs
"dependencies": {
"Library.A": "",
"Library.B": ""
}
var c = new Configuration();
c.AddJsonFile("config.json");
a.UseServices(services => …);
ソースコードとパッ
ケージ利用情報だけ
をアップロード
サーバー上で
編集可能
.NETランタイムや、
ライブラリの不足・更新
はクラウドから取得
利用するパッケージ
の情報ファイル
ポイント
• 選べる実行方法
• IL配布(JIT)
• デスクトップなら割とこれが便利
• ネイティブ配布(.NET Native)
• 携帯デバイス向け
• ソースコード配置(Cloud Mode)
• サーバー向け
• 特に共有ホスティングなクラウド サーバー
Portable Class Library
複数の「標準ライブラリ」
いろんな実行環境の共通部分
問題: 複数の標準ライブラリ
• マイクロソフト製品だけでも…
デスクトップ
クライアント アプリ
Phone/タブレット
クライアント アプリ
サーバー アプリ
共通部分
この共通部分だけを
「標準」にすべき?
.NET Native
Cloud Mode
問題: 複数の標準ライブラリ
• まして今、Xamarin (Mono)
• Xamarin.iOS、Xamarin.Android
Windows
デスクトップWindows
タブレット/Phone
Linux
サーバー
この共通部分だけを
「標準」にすべき?
Windows
サーバー
iOS
Android
.NET FrameworkとMono
C#
VB
F#
C#
CLR
Mono
ランタイム
.NET Full
プロファイル
.NET Core
プロファイル
.NET Full
(サブセット)
iOS向け
プロファイル
Android向け
プロファイル
.NET
Framework
Mono
コンパイラー 実行環境 ライブラリ
実行環境にはかなり
の互換性がある 標準で使える
ライブラリが違う
どこでも使えそうに見えても…
• 例えばファイル システム
• 最近のWindowsはいろんなプロパティを持ってる
• 画像ファイルなんかだと:
サムネイル画像、撮影日時、画像サイズ、タグ
• 検索インデックスも張ってる
• ストア アプリだとファイル システムすら制限下
• ユーザーの許可がないファイルには触れない
こういうものも標準に含めたいか?
一番制限がきつい環境に合わせて標準ライブラリを作るべき?
汎用 VS 特定環境
どこでも動く
• 最大公約数
• 動作保証に時間が
かかる
特定環境で動く
• 高機能
• 早く提供できる
Portable Class Library
• 実行環境ごとに
別の「標準ライブラリ」
メタデータを用意
• ライブラリ側でどの
実行環境をターゲットに
するか選ぶ
実行環境ごとに
別メタデータを提供
ターゲット選択
Portable Class Library
• 例: 2環境
共通部分
Portable Class Library
• 例: 3環境
共通部分
.NET vNext
• ぶっちゃけ3系統別実装 (主用途も別)
• JIT
• .NET Native
• Cloud Mode
• 1つの“標準”ライブラリで保守するのは大変
• どうしても事前ネイティブ化しにくい…
• サーバーにGUIコンポーネント要るの?…
• フットプリント的に余計なもの載せれない…
既存品とはいえ、ちゃんと次世代でも更新あり
• 64ビット対応強化
• SIMD演算対応
new!
new!
PCLみたいな仕組み必須
ポイント
• 複数の“標準”
• 用途によって
• デスクトップ、携帯デバイス、クラウド
• 実装によって
• JIT、事前ネイティブ化、ソースコード配置
• 他OSへのポーティング
ME
SE
EE
v2.0
v3.0
v4.0
× 包含関係では不十分 ○ 複数の“標準”の共通部分管理
3時間目
• C#言語機能
• generics
• iterator
• LINQ
• dynamic
• async/await
• .NET Compiler Platform
1
2
3
C#の歴史
C# 1.0
• Managed
C# 2.0
• Generics
• Iterator
C# 3.0
• LINQ
C# 4.0
• Dynamic
C# 5.0
• Async
※VB 7~11の歴史でもある
ジェネリック
C# 2.0
C++で言うところのtemplate
C++ templateと.NET Genericsの違い
型違いの処理
• 型だけ違う処理、コピペで書いていませんか
int Max(int x, int y)
{
return x > y ? x : y;
}
class IntStack
{
void Push(int item)
{ … }
int Pop()
{ … }
}
double Max(double x, double y)
{
return x > y ? x : y;
}
class DoubleStack
{
void Push(double item)
{ … }
double Pop()
{ … }
}
ジェネリック†
• 型をパラメーター化
† generics。MS翻訳ルール的に、語尾 s は取るんですって
複数形のs扱いで。単複の区別のない言語に訳すとき
class Stack<T>
{
void Push(T item)
{ … }
T Pop()
{ … }
}
T Max<T>(T x, T y)
where T : IComparable<T>
{
return x.CompareTo(y) > 0 ? x : y;
}
int Max(int x, int y)
{
return x > y ? x : y;
}
class IntStack
{
void Push(int item)
{ … }
int Pop()
{ … }
}
型の直行化
• 要素の型と、処理・要素管理は分けましょう
要素の型
処理
int
byte
double
string
… Max
Min
Average
…
管理方式
List
LinkedList
Stack
…
型の直行化
• 要素の型と、処理・要素管理は分けましょう
要素の型
処理
int
byte
double
string
… Max
Min
Average
…
管理方式
List
LinkedList
Stack
…
Lパターン
Mパターン
Nパターン
分けて作らないと L×M×N 通りのパターン
分けて作ると L+M+N 通り
2.0からなので…
• 1.0の頃の名残がちらほら…
• 今となっては
GroupCollection
MatchCollection
AttributeCollection
StringCollection
…
IEnumerable<Group>
IEnumerable<Match>
IEnumerable<Attribute>
IEnumerable<string>
…
IReadOnlyCollection<Group>
IReadOnlyCollection<Match>
IReadOnlyCollection<Attribute>
IReadOnlyCollection<string>
…
もしくは
1つの型で済む
†
† System.dllに実在する型。ごくごく一部の抜粋。
.NETのジェネリック
• ILレベル対応
• メタデータがちゃんと残る
• リフレクションで厳密な型をとれる・区別できる
• ジェネリック用命令持ってる
• JIT時に展開
• キャストとかの不要コードが消える
• 値型のボックス化も消える
• 値型の展開はかなりパフォーマンスに寄与
おまけ: C++のtemplate
• コンパイル時に展開
• 超高機能なマクロみたいなもの
• ○ 実行時のパフォーマンスいい
• ○ かなり自由が効く
• × 実行可能ファイル サイズが肥大化しがち
• × コンパイル エラーが出た時結構悲惨
おまけ: Javaのジェネリック
• 型消去
• コンパイル時に実は型が消えてる
• 全部object扱い
• ○? Java 1.0の頃からbytecode命令増えてない
• × 実行時にリフレクションで情報とれない
• ×キャストが挟まる
• × 全然違う型にキャストできちゃう(実行時例外)
いろいろ窮屈な面も
• .NETのジェネリックでは、インターフェイス制
約かけないとメソッドすら呼べない
static Type Max<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
いろいろ窮屈な面も
• 特に困るのが演算子使えないこと
• 実体は静的メソッドなので
static T Sum<T>(T[] array)
{
T sum = default(T);
foreach (var x in array) sum += x;
return sum;
} コンパイル エラー
演算子定義されてない
いろいろ窮屈な面も
• dynamicでごまかせなくはないけども…
• パフォーマンス出ないので最後の手段
static T Sum<T>(T[] array)
{
dynamic sum = default(T);
foreach (var x in array) sum += x;
return sum;
} 実行時コード生成で
+演算子が呼ばれる
ポイント
• 型のパラメーター化
• 似て非なるコピペ コードの解消
• 型の直行化
• {int, byte, string, …} × {List, Stack, Queue, …}
• .NETのジェネリックはILレベル対応
• メタデータあり
• 実行時にリフレクションで情報とれる
• JIT時に展開
• キャストなどの不要なコードは挟まらない
イテレーター
C# 2.0
イテレーター生成用の構文
データの列挙
• プログラム中、データの列挙は非常に多い
• データを使う側はすごく楽
• 作る側、加工する側は?
foreach (var x in data)
{
Console.WriteLine(x);
}
データの列挙の例
• substringの列挙
• データを作る側と使う側を分けないなら
static void WriteSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
Console.WriteLine(s.Substring(i, len));
}
いつもConsole.Writeしたいわけじゃない
substringを使いたいたびに同じコード書くの?
データの列挙の例
• substringの列挙、分けたいなら
• ↓こんな感じのクラスを書けばいいんだけど…
class GetSubstringEnumerator
{
public string Current { get; private set; }
string _s; int _len; int _i;
public GetSubstringEnumerator(string s)
{
_s = s; _len = s.Length; _i = 0;
}
public bool MoveNext()
{
for (; _len >= 1; _len--, _i = 0)
for (; _i <= _s.Length - _len; )
{
Current = _s.Substring(_i, _len);
_i++;
return true;
}
return false;
}
}
こういうクラスを
イテレーター(iterator)とか
列挙子(enumerator)って言う
作るの結構面倒
イテレーターの例
• substringの列挙
static IEnumerable<string> GetSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
yield return s.Substring(i, len);
}
foreach (var x in GetSubstrings("abcd"))
Console.WriteLine(x);
実装側
使う側
イテレーター ブロック†
(= yield returnを持つ関数ブロック)
イテレーター クラスを自動生成
内部実装(全体像)
• クラス生成
class SubstringEnumerable : IEnumerator<string>, IEnumerable<string>
{
readonly string _s;
int _len;
int _i;
int _state = 0;
public SubstringEnumerable(string s) { _s = s; }
public string Current { get; private set; }
public bool MoveNext()
{
if (_state == 1) goto STATE1;
if (_state == -1) goto END;
_state = 1;
_len = _s.Length;
LOOP1BEGIN: ;
if (!(_len >= 1)) goto LOOP1END;
_i = 0;
LOOP2BEGIN: ;
if (!(_i <= _s.Length - _len)) goto LOOP2END;
_state = 1;
Current = _s.Substring(_i, _len);
return true;
STATE1: ;
_i++;
goto LOOP2BEGIN;
LOOP2END: ;
_len--;
goto LOOP1BEGIN;
LOOP1END: ;
_state = -1;
END: ;
return false; }
public void Reset() { throw new NotImplementedException(); }
public void Dispose() { }
object IEnumerator.Current { get { return Current; } }
public IEnumerator<string> GetEnumerator()
{
if(_state == 0) return this;
else return new SubstringEnumerable(_s).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
static IEnumerable<string> GetSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
yield return s.Substring(i, len);
}
内部実装(ローカル変数)
• ローカル変数 → フィールド
class SubstringEnumerable : IEnumera
{
readonly string _s;
int _len;
int _i;
int _state = 0;
public SubstringEnumerable(strin
public string Current { get; pri
public bool MoveNext()
{
if (_state == 1) goto STATE1
if (_state == -1) goto END;
static IEnumerable<string> GetSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
yield return s.Substring(i, len);
}
内部実装(yield return)
• yield return → 状態記録、return、caseラベル
• 中断と再開
if (_state == 1) goto STATE1;
if (_state == -1) goto END;
_state = 1;
_len = _s.Length;
LOOP1BEGIN: ;
if (!(_len >= 1)) goto LOOP1END;
_i = 0;
LOOP2BEGIN: ;
if (!(_i <= _s.Length - _len)) go
_state = 1;
Current = _s.Substring(_i, _len);
return true;
STATE1: ;
_i++;
goto LOOP2BEGIN;
static IEnumerable<string> GetSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
yield return s.Substring(i, len);
}
switch(_state)
{
case 0:
for (_len = _s.Length; _len >= 1; _len--)
for (_i = 0; _i <= _s.Length - _len; _i++)
{
_state = 1;
Current = _s.Substring(_i, _len);
return true;
case 1:;
}
_state = -1;
}
内部実装(yield return)
• yield returnの部分、意味合いとしては†
static IEnumerable<string> GetSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
yield return s.Substring(i, len);
}
yield return以外の
場所はほぼ同じ
yield return x;
_state = 1;
Current = x;
return true;
case 1:;
† forループ内にラベル張れないからさっきみたいな複雑なコードになるけども
switchで囲う
内部実装(中断と再開)
• yield returnの部分、意味合いとしては
• 中断と再開
yield return x;
_state = 1;
Current = x;
return true;
case 1:;
状態の記録
現在の値の保持
復帰用のラベル
おまけ: 他の言語だと
• 最近の言語は結構似た機能†持ってる
• スタック丸ごとキャプチャしてしまうもの
• 中断時に記録、再開時に復元
• 式を継続渡しスタイル(CPS)に変換してしまうもの
• スレッド使う(さすがに性能的に論外だけども)
• 割と機械的な置き換えなので、マクロでも
† 他の言語だとジェネレーター(generator)って呼ばれることが多い
#define BEGIN_ITERATOR
switch(_state)
{
case 0:
#define YIELD(STATE, VALUE)
_state = STATE;
_current = VALUE;
return true;
case STATE:;
#define END_ITERATOR
_state = -1;
default:;
}
return false;
おまけ: 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;
}
}
ちなみに
• コーディング面接で有名な某社の社員さん曰く、
• 例に使ったのsubstring列挙も割とよく出てくるパ
ターン
• 中断と再開って大事
アルゴリズムの問題はかなりの割合、
イテレーターを使うとあっさり書ける
「
」
ポイント
• データ列挙は多い
• データを作る側と使う側をきっちり分離しよう
と思うと結構面倒
• 特に、作る側
• 作る側を簡単化する仕組みがイテレーター
static IEnumerable<string> GetSubstrings(string s)
{
for (var len = s.Length; len >= 1; len--)
for (var i = 0; i <= s.Length - len; i++)
yield return s.Substring(i, len);
}
LINQ
(Language Integrated
Query)
C# 3.0
データ処理の直行化
LINQ
• データ処理を言語統合
• ほとんどはライブラリで実現
• System.Linq名前空間
var source = new[] { 1, 2, 3, 4, 5 };
var filtered = source
.Where(x => x <= 3) // 1, 2, 3
.Select(x => x * x); // 1, 4, 9
Enumerableクラスの
WhereメソッドとSelectメソッド
が呼ばれるだけ
条件を満たす要素だけ残す
要素ごとに処理をかける
データ処理の直行化
• データの入力、加工、出力は分けましょう
ユーザー入力から
Console.Read…
配列から
{ 1, 2, 3, … }
データベースから
SELECT x FROM t
ファイルから
File.Read…
1, 2, 3 変換
x => x * x 1, 4, 9
1, 2, 3 選択
x => x < 3 1, 2
1, 2, 3 グループ化
x => x % 2 {1, 3},
{2}
コンソールに
Console.Write…
配列に
ToArray()
データベースに
INSERT INTO t
ファイルに
File. Write…
入力 加工 出力
データ処理の直行化
• 掛け算を足し算に
ユーザー入力から
Console.Read…
配列から
{ 1, 2, 3, … }
データベースから
SELECT x FROM t
ファイルから
File.Read…
1, 2, 3 変換
x => x * x 1, 4, 9
1, 2, 3 選択
x => x < 3 1, 2
1, 2, 3 グループ化
x => x % 2 {1, 3},
{2}
コンソールに
Console.Write…
配列に
ToArray()
データベースに
INSERT INTO t
ファイルに
File. Write…
入力 加工 出力
Lパターン Mパターン Nパターン
分けて作らないと L×M×N 通りのパターン
分けて作ると L+M+N 通り
yield returnで実装できる
• 列挙子から別の列挙子を作る処理
• ここまではC# 2.0
• これに加えて、C# 3.0では…
IEnumerable<R> Select<S, R>(
IEnumerable<S> source,
Func<S, R> selector)
{
foreach (var x in source)
yield return selector(x);
}
IEnumerable<T> Where<T(
IEnumerable<T> source,
Func<T, bool> predicate)
{
foreach (var x in source)
if (predicate(x))
yield return x;
}
列挙子を引数にとって列挙子を返す
yieldがあれば実装簡単
C# 3.0
• ラムダ式
• 匿名型
• 拡張メソッド
ラムダ式
• 匿名関数を簡単に書ける
• =>演算子
• goes to (~になる)演算子
• 左が引数で、右が関数本体
• 型推論も効いてる
source.Select(x => x * x);
(シーケンスの全要素を二乗)
そもそも: 匿名関数
• メソッドの自動生成
IEnumerable<int> Triple(IEnumerable<int> input)
{
return input.Select(x => 3 * x);
}
IEnumerable<int> Triple(IEnumerable<int> input)
{
return input.Select(X);
}
int X(int x) { return 3 * x; }
ローカル変数のキャプチャ
• 実はクラス生成
IEnumerable<int> Multiply(IEnumerable<int> input)
{
var a = int.Parse(Console.ReadLine());
return input.Select(x => a * x);
}
IEnumerable<int> Multiply(IEnumerable<int> input)
{
var _ = new Anonymous();
_.a = int.Parse(Console.ReadLine());
return input.Select(_.X);
}
class Anonymous
{
public int a;
public int X(int x)
{
return a * x;
}
}
ローカル変数が
フィールドに昇格
匿名型
• 1か所でしか使わないような型は作らなくてい
い
• immutableなクラスを自動生成
• GetHashCode、等値比較、ToStringを完備
source.GroupBy(p => new { p.X, p.Y });
(XとYでグループ化)
class Anonymous
{
public int X { get; private set; }
public int Y { get; private set; }
public Anonymous(int x, int y) { X = x; Y = y; }
}
拡張メソッド
• 静的メソッドを後置き記法で書ける
• 単に語順を変えるだけ
source.Select(x => x * x);
System.Linq.Enumerable.Select(
source, x => x * x);
同じ意味
語順を変えるだけで
• 語順のインパクト意外と大きい
var result = data
.Where(x => x < 3)
.Select(x => x * x)
.GroupBy(x => x % 2)
.Select(g => g.Sum());
var result1 =
Select(
GroupBy(
Select(
Where(
data,
x => x < 3),
x => x * x),
x => x % 2),
g => Sum(g));
逆順 処理順
( ) が遠い
( ) が近い
普通の静的メソッド 拡張メソッド
静的メソッド
• “static”と言ってもいろいろ
static bool globalFlag;
いつどこで誰が書き換えるか
わからないのがダメ
静的フィールド(書き換え可能)
const int Max = 100;
static readonly TimeSpan interval = TimeSpan.FromSeconds(1);
定数 or 読み取り専用静的フィールド
書き換え禁止すれば無害
static int Clip(int x) { return Math.Max(x, Max); }
静的メソッド
無害なものにしか触れない限り、無害
静的メソッド
• “static”と言ってもいろいろ
static bool globalFlag;
いつどこで誰が書き換えるか
わからないのがダメ
静的フィールド(書き換え可能)
const int Max = 100;
static readonly TimeSpan interval = TimeSpan.FromSeconds(1);
定数 or 読み取り専用静的フィールド
書き換え禁止すれば無害
static int Clip(int x) { return Math.Max(x, Max); }
静的メソッド
無害なものにしか触れない限り、無害
純粋関数(pure function)
書き換えが起こらないメソッド
= 同じ引数を与えたら常に同じ結果しか返らない
= テストしやすくていい
ポイント
• C# 3.0
• ラムダ式
• 匿名型
• 拡張メソッド
• 小さくて、汎用的な機能の集まり
• LINQ以外でも有用
LINQ (データ処理用構文・ライ
ブラリ)に関連して入った機能
dynamic型
C# 4.0
ダック タイピング用の型
おさらい: メタデータ
• プロパティ名とかは、本来、実行時に要らない
IL_0000: ldarg.0
IL_0001: ldfld int32 T::X
IL_0006: ldarg.0
IL_0007: ldfld int32 T::Y
IL_000c: mul
IL_000d: ldarg.0
IL_000e: ldfld int32 T::Z
IL_0013: mul
IL_0014: ret
push ebp
mov ebp,esp
cmp dword ptr ds:[5011058h],0
je 00FE2A01
call 74B7AEA8
mov eax,dword ptr [ebp+8]
lea edx,[ebp+8]
imul eax,dword ptr [edx+4]
lea edx,[ebp+8]
imul eax,dword ptr [edx+8]
pop ebp
ret 0Ch
ILの状態 実行時(ネイティブ化した状態)
名前が残ってる
名前が消えて、
レイアウト情報
だけになってる
ダック タイピング†
• 同じ名前のメンバーを持っていれば
同じ型扱いできないか
† アヒルのように歩き、アヒルのように鳴くなら、それはアヒルだ」
という論法からきた比喩表現
class Point
{
public int X { get; set; }
public int Y { get; set; }
public void Add(Point p)
{
X += p.X;
Y += p.Y;
}
}
ダック タイピング†
• 同じ名前のメンバーを持っていれば
同じ型扱いできないか
† アヒルのように歩き、アヒルのように鳴くなら、それはアヒルだ」
という論法からきた比喩表現
class Point
{
public int X { get; set; }
public int Y { get; set; }
public void Add(Point p)
{
X += p.X;
Y += p.Y;
}
}
?
XとYというプロパティ
(またはフィールド)を
持っている任意の型を
使いたい
こういう処理にはリフレクション
(メタデータの実行時利用)が必要
dynamic型
• ダック タイピング用の型
class Point
{
public int X { get; set; }
public int Y { get; set; }
public void Add(dynamic p)
{
X += p.X;
Y += p.Y;
}
}
XとYというプロパティ
(またはフィールド)を
持っている任意の型を
使える
もちろん、内部的には
リフレクション使ってる
dynamic型
• 結構用途が限られる
• そもそもC#でダック タイピングしたい状況が稀
• ほぼ、外部との連携用
• COMとの連携
• 動的言語との連携
• JSONみたいなスキーマレスなデータ読み書き
• その他、例えばできること
• 多重ディスパッチ
• できないこと
• メタプログラミング
• C#のスクリプト的実行
例: 動的言語との連携
• DLR (Dynamic Language Runtime)
• 例: IronPython
var py = IronPython.Hosting.Python.CreateEngine();
dynamic p = py.Execute("['a', 'b', 1, 2]");
for (var i = 0; i < 4; i++)
Console.WriteLine(p[i]);
Pythonコード
例: 多重ディスパッチ
• 静的な型に対して
class Base { }
class A : Base { }
class B : Base { }
例:多重ディスパッチ
• 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"; }
}
動的な呼び出し
例:多重ディスパッチ
• 呼び出し例
static void Main()
{
Dispatch(new A(), new A()); // A - A
Dispatch(new A(), new B()); // A - B
Dispatch(new B(), new B()); // others
Dispatch(new B(), new A()); // others
}
static void Dispatch(Base x, Base y)
{
Console.WriteLine(x.Dispatch(y));
}
dynamic型の内部実装
• コード生成結果
dynamic X(dynamic x)
{
return x.X;
}
object X(object x)
{
if (_site1 == null)
{
_site1 = CallSite<Func<CallSite, o
Binder.GetMember(CSharpBinderF
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(
}));
}
return _site1.Target(_site1, x);
}
実際にはobject
動的コード生成
用の情報
これが本体
CallSite.Targetの中身
• メソッドを動的コード生成してる
• 生成したメソッドはキャッシュして持っておく
(inline method cache)
static object _anonymous(CallSite site, object x)
{
return site.Targetを更新する処理
}
_site1.Targetの初期状態
CallSite.Targetの中身
• メソッドを動的コード生成してる
• 生成したメソッドはキャッシュして持っておく
(inline method cache)
• 同じ型に対して何度も呼ぶ分には高性能
static object _anonymous(CallSite site, object x)
{
if (x is Point) return ((Point)x).X;
else return site.Targetを更新する処理
}
メソッドXにPoint型のインスタンスを渡した後
1行追加
単なる型判定+キャスト
CallSite.Targetの中身
• メソッドを動的コード生成してる
• 生成したメソッドはキャッシュして持っておく
(inline method cache)
static object _anonymous(CallSite site, object x)
{
if (x is Point) return ((Point)x).X;
if (x is Vector3D) return ((Vector3D)x).X;
else return site.Targetを更新する処理
}
さらに、メソッドXにVector3d型のインスタンスを渡した後
もう1行追加
ちなみに、最近はスクリプト言語でも、
内部的に型を作って、inline method cache
で高速化してる
“heavy” dynamic
• 用途によっては高性能なものの…
• 多くの場合、過剰スペック
• できるけど過剰スペックな例
• JSONみたいなスキーマレスなデータ読み書き
• もっと”light-weight”なdynamicが必要
p.X;
p.M();
p.Get("X");
p.Invoke("M");
例: 規約ベースの置き換え
一時期、「p.$x を p["x"] と解釈しよう」
という提案はあったけども、結局立ち消え中
できないこと
• メンバー名がコンパイル時に既知でないとダメ
• なのでメタプログラミングには使えない
• そのためにはもっと低レイヤーなAPI使う
• IL Emit
• Expression Tree
• Roslyn
dynamic x = p;
dynamic y = q;
y.X = x.X;
y.Y = x.Y;
コンパイル時に既知
ポイント
• dynamic型
• C#でダック タイピング
• 主に外部との連携用
• inline method cache
• 用途があえば結構高性能
• 用途によっては過剰スペック
• メタプログラミング用ではない
async/await
C# 5.0
非同期処理
スレッド関連おさらい
• 非同期処理
• マルチタスク
• UIスレッドを止めない
• I/O (外の世界との入出力待ち)
• Taskクラスを使いましょう
• スレッド プール
• I/O完了ポート
割と避けれないこと
なんだけども…
非同期処理しんどい
• 普通に非同期処理やったらコールバック地獄
• begin/end地獄
• イベント地獄
• then地獄(ContinueWith地獄)
x.BeginX(args, state, ar =>
{
var result = x.EndX();
…
});
x.XCompleted += (s, arg) =>
{
var result = arg.Result;
…
});
x.XAsync();
x.XAsync()
.ContinueWith(t =>
{
var result = t.Result;
…
};非同期呼び出しが1回だから
この程度で済んでる
• 複数の確認ダイアログ表示
面倒な非同期処理の例
確認 1
チェック
確認 2
チェック
確認 3
チェック
No
No
Yes
Yes
Yes
確認フロー
結果表示
No
ゲームで
アイテムを
合成します
レア アイテムですよ?
合成強化済みですよ?
もう強化限界ですよ?
ユーザーから
の入力待ちも
非同期処理
同期処理
if (Check1.IsChecked)
{
var result = Dialog.ShowDialog("確認 1", "1つ目の確認作業");
if (!result) return false;
}
if (Check2.IsChecked)
{
var result = Dialog.ShowDialog("確認 2", "2つ目の確認作業");
if (!result) return false;
}
if (Check3.IsChecked)
{
var result = Dialog.ShowDialog("確認 3", "3つ目の確認作業");
if (!result) return false;
}
return true;
非同期処理 (旧)
• 画面に収まるように
フォント サイズ調整
• 4pt
• ほんの84行ほど
• ちなみに
• 部分部分を関数化して多
少は整理できる
• ダイアログ3つだからまだ
この程度で済む
if (Check1.IsChecked)
{
Dialog.BeginShowDialog("確認 1", "1つ目の確認作業", result =>
{
if (!result)
{
onComplete(false);
return;
}
if (.Check2.IsChecked)
{
Dialog.BeginShowDialog("確認 2", "2つ目の確認作業", result2 =>
{
if (!result2)
{
onComplete(false);
return;
}
if (Check3.IsChecked)
{
Dialog.BeginShowDialog("確認 3", "3つ目の確認作業", result3 =>
{
onComplete(result3);
});
}
else
onComplete(true);
});
}
else if (Check3.IsChecked)
{
Dialog.BeginShowDialog("確認 3", "3つ目の確認作業", result3 =>
{
onComplete(result3);
});
}
else
onComplete(true);
});
}
else if (Check2.IsChecked)
{
Dialog.BeginShowDialog("確認 2", "2つ目の確認作業", result =>
{
if (!result)
{
onComplete(false);
return;
}
if (Check3.IsChecked)
{
Dialog.BeginShowDialog("確認 3", "3つ目の確認作業", result3 =>
{
onComplete(result);
});
}
else
onComplete(true);
});
}
else if (Check3.IsChecked)
{
Dialog.BeginShowDialog("確認 3", "3つ目の確認作業", result3 =>
{
onComplete(result3);
});
}
else
onComplete(true);
非同期処理(C# 5.0)
if (this.Check1.IsChecked ?? false)
{
var result = await Dialog.ShowDialogAsync("確認 1", "1つ目の確認作業");
if (!result) return false;
}
if (this.Check2.IsChecked ?? false)
{
var result = await Dialog.ShowDialogAsync("確認 2", "2つ目の確認作業");
if (!result) return false;
}
if (this.Check3.IsChecked ?? false)
{
var result = await Dialog.ShowDialogAsync("確認 3", "3つ目の確認作業");
if (!result) return false;
}
return true;
• 同期処理と比べてawait演算子が増えただけ
• ダイアログの数が増えても平気
イテレーターと似た仕組み
• イテレーター(ジェネレーター)があれば、割と
単純なラッパーで非同期処理も可能
• 要は、「中断と再開」
• 例えば、TypeScriptでは
• 現状でもawaitのMS社内実装は持ってる
• いまだと、生成されるJavaScriptが悲惨すぎて大変
• EcmaScriptにジェネレーターが実装されてから、
TypeScriptにawaitを追加する予定
参考: C#のイテレーター(再)
• 中断と再開
class MethodEnumerator : IEnumerator<int>
{
public int Current { get; private set; }
private int _state = 0;
public bool MoveNext()
{
switch (_state)
{
case 0:
Current = 1;
_state = 1;
return true;
case 1:
Current = 2;
_state = 2;
return true;
case 2:
default:
return false;
}
}
}
IEnumerable<int> Method()
{
yield return 1;
yield return 2;
}
Current = 1;
_state = 1;
return true;
case 1:
状態の記録
中断
再開用のラベル
基本的な考え方
• 概念としては イテレーター+継続呼び出し
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;
中断
状態の記録
結果の受け取り
再開用のラベル
非同期処理が終
わったら続きから
呼び出してもらう
実際の展開結果
• 実際はもう少し複雑
• Awaiterというものを介する(Awaitableパターン)
_state = 1;
var awaiter1 = task1.GetAwaiter();
if (!awaiter1.IsCompleted)
{
awaiter1.OnCompleted(a);
return;
}
case 1:
var x = awaiter1.GetResult();
• Awaiterを自作することで
awaitの挙動を変更可能
• Task以外もawait可能
• GetAwaiterは拡張メソッ
ドでもOK
Awaitable
• Awaitableなクラスは自作可能
• 実装次第でいろいろ
• Windowd Runtime
• IAsyncOperationインターフェイスとかをawaitできる
• TaskのAwaitable実装
• UIスレッドへのディスパッチを内部的にやってくれる
• そうしたくない場合の実装もある
• ConfigureAwait
おまけ: C++ 1y
• C++にもawaitが載るかも
• C++ 17に向けて標準化案出てる
• C++/CX向けの実装を元にMSが提案
• 前述の通り、ついでにジェネレーターも
future<void> f(stream str) async
{
shared_ptr<vector> buf = ...;
int count = await str.read(512, buf);
return count + 11;
}
おまけ: immutable
• 並列処理といえばimmutableだけども
• 書き換えが起こらないなら複数のスレッドで共有し
ても安全
• この用途だと、C++のconstは不十分
• あれは参照渡しを安全に行う用であって
• 呼び出し元の側ではconstとは限らず、書き換わる
可能性あり
• あと、mutable修飾子を付ければconstなオブジェク
トすら書き換えれる
ポイント
• 非同期処理は、避けれないんだけども面倒
• async/awaitで多少マシに
• 実装的にはイテレーターと同様、中断と再開
.NET
Compiler Platform
Compiler as a Service
コンパイラーの内部データを活用
.NET Compiler Platform†
• C#/VBコンパイラーを再設計・再実装
• .NET実装
• C#実装のC#コンパイラー
• VB実装のVBコンパイラー
• コンパイラーの内部データを誰でも自由に使える
† コードネーム“Roslyn”って呼ばれてたやつの正式名称
コンパイラーのサービス化、
プラットフォーム化
用途
• C#スクリプティング
• C#で設定ファイル書きたい(むしろXMLがいや)
• アプリの再起動なしでロジック更新
• ソースコード配置
• .NET vNext, Cloud Mode
• コード解析
• コードのインデックス化†
• サーバー ビルド、テスト
• IDE連携 現状の最優先事項
† .NETの参照ソースコードが実際やってる
http://referencesource.microsoft.com/
構文ハイライト
• C#は文脈キーワードだらけ
static IEnumerable<async> async()
{
var var = "var";
var yield = new async();
yield return yield;
Func<string, Task<int>> async = async x =>
{
await Task.Delay(100);
return int.Parse(x);
};
var await = async(var).GetAwaiter().GetResult();
}
メソッド名
クラス名
変数 キーワード
リアルタイム エラー検出
• エラー検出タイミングがビルド時とか遅い
• Visual Studioは常時やってる
コード補完
• タイピングめんどくさい
• 文法やライブラリ、いちいち覚えたくない
リファクタリング
• 最初からきれいなコード書くのめんどくさい
• でもほっときたくない
ということで
• 今、コンパイラーに求められる要件
• ソースコードのどこからどこまで(何行何列目)が
何かという情報がとれる
• 文脈に応じてソースコードを生成したり、書き替え
たりできる
• リアルタイム処理を必要とするので、パフォーマン
スも求められる
実はこれまで
• コンパイラー(パーサー)を2重開発してた
• コンパイル用
• IDE用
• まして、サード パーティ製コード解析プラグイン
も含めると、3重開発
• Java (EclipseとかIntelliJとか)でも
• (去年ぐらいによく言われてたけども)
「Eclipseが対応するまでJava 8プレビュー試せない
や」
おまけ: 他の環境(Clang)
• Clangはその辺りをゴールの1つに掲げてる
• IDEで使う前提
• リファクタリングに使いやすいデータ構造の構文木
• インクリメンタル コンパイルとかもしやすい
IDE連携まで考えると
• 簡単そうに見える文法ですら、実装コストかな
り高い
• 2重開発はそれだけ大変
• だからIDEを信用しない/できない人も多い
• IDE対応待ってられない/待ちたくない
• .NET Compiler Platformはそれを解消
• C#に新機能を足しやすくなる
• C# 6.0
C# 6.0 (予定)の例
public class Point(int x, int y)
{
public int X { get } = x;
public int Y { get } = y;
}
Primary Constructor / Property Expressions
while ((var line = stream.ReadLine()) != null)
line ...
if ((var x = obj as Point) != null)
x ...
Declaration Expressions
immutableな型を作りやすく
「式」で書けることの幅が広がる
ポイント
• 実行可能ファイルを作るだけがコンパイラーの
仕事じゃない
• スクリプト実行
• コード解析
• 特に、IDE連携
• しかも、リアルタイム処理
• C#/VBコンパイラーの再設計
= .NET Compiler Platform
このあたりまで考えると
ちょっとした言語機能を
足すのも大変
C#/.NETがやっていること 第二版

More Related Content

What's hot

Code Contracts in .NET 4
Code Contracts in .NET 4Code Contracts in .NET 4
Code Contracts in .NET 4信之 岩永
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているKoichi Tanaka
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化Gosuke Miyashita
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門Norishige Fukushima
 
PHP の GC の話
PHP の GC の話PHP の GC の話
PHP の GC の話y-uti
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来についてshinjiigarashi
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!masakazu matsubara
 
PHPとシグナル、その裏側
PHPとシグナル、その裏側PHPとシグナル、その裏側
PHPとシグナル、その裏側do_aki
 
ネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けモノビット エンジン
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかYuki Miyatake
 
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!amusementcreators
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
 
ネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けモノビット エンジン
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話Kumazaki Hiroki
 
C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること信之 岩永
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法についてYuji Otani
 
メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろうKota Mizushima
 
オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫Yuta Imai
 

What's hot (20)

Code Contracts in .NET 4
Code Contracts in .NET 4Code Contracts in .NET 4
Code Contracts in .NET 4
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っている
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
 
PHP の GC の話
PHP の GC の話PHP の GC の話
PHP の GC の話
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!
 
PHPとシグナル、その裏側
PHPとシグナル、その裏側PHPとシグナル、その裏側
PHPとシグナル、その裏側
 
ネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分け
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
 
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
Gpu vs fpga
Gpu vs fpgaGpu vs fpga
Gpu vs fpga
 
ネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分け
 
本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話本当は恐ろしい分散システムの話
本当は恐ろしい分散システムの話
 
C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろう
 
オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 

Viewers also liked

ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発慎一 古賀
 
それっぽく、適当に
それっぽく、適当にそれっぽく、適当に
それっぽく、適当に信之 岩永
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略信之 岩永
 
ゲームの中の人工知能
ゲームの中の人工知能ゲームの中の人工知能
ゲームの中の人工知能Youichiro Miyake
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略信之 岩永
 
Orange Cube 自社フレームワーク 2015/3
Orange Cube 自社フレームワーク 2015/3Orange Cube 自社フレームワーク 2015/3
Orange Cube 自社フレームワーク 2015/3信之 岩永
 
C# TreeViewを使用する1
C# TreeViewを使用する1C# TreeViewを使用する1
C# TreeViewを使用する1Hiroki Takahashi
 
Word bench nagoya 5月度
Word bench nagoya 5月度Word bench nagoya 5月度
Word bench nagoya 5月度Yoji Izumi
 
C#によるファイルの読み書き
C#によるファイルの読み書きC#によるファイルの読み書き
C#によるファイルの読み書きHiroki Takahashi
 
C# Database操作1 接続と切断-
C# Database操作1  接続と切断-C# Database操作1  接続と切断-
C# Database操作1 接続と切断-Hiroki Takahashi
 
C# FileSystemWatcherコントロールを使用したアプリケーションの作成
C# FileSystemWatcherコントロールを使用したアプリケーションの作成C# FileSystemWatcherコントロールを使用したアプリケーションの作成
C# FileSystemWatcherコントロールを使用したアプリケーションの作成Hiroki Takahashi
 
C# Database操作2 データの取得-
C# Database操作2  データの取得-C# Database操作2  データの取得-
C# Database操作2 データの取得-Hiroki Takahashi
 
C# TreeViewを使用する2
C# TreeViewを使用する2C# TreeViewを使用する2
C# TreeViewを使用する2Hiroki Takahashi
 
XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」
XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」
XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」akipii Oga
 
Bodlogiin code
Bodlogiin codeBodlogiin code
Bodlogiin codeorgil
 
Photoshopでバナー "いい感じ" に制作せよ!
Photoshopでバナー "いい感じ" に制作せよ!Photoshopでバナー "いい感じ" に制作せよ!
Photoshopでバナー "いい感じ" に制作せよ!Hiroki Shibata
 
12 分くらいで知るLuaVM
12 分くらいで知るLuaVM12 分くらいで知るLuaVM
12 分くらいで知るLuaVMYuki Tamura
 

Viewers also liked (20)

ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
 
それっぽく、適当に
それっぽく、適当にそれっぽく、適当に
それっぽく、適当に
 
Modern .NET
Modern .NETModern .NET
Modern .NET
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略
 
.NET vNext
.NET vNext.NET vNext
.NET vNext
 
ゲームの中の人工知能
ゲームの中の人工知能ゲームの中の人工知能
ゲームの中の人工知能
 
今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略今から始める、Windows 10&新.NETへの移行戦略
今から始める、Windows 10&新.NETへの移行戦略
 
Deep Dive C# 6.0
Deep Dive C# 6.0Deep Dive C# 6.0
Deep Dive C# 6.0
 
Orange Cube 自社フレームワーク 2015/3
Orange Cube 自社フレームワーク 2015/3Orange Cube 自社フレームワーク 2015/3
Orange Cube 自社フレームワーク 2015/3
 
C# TreeViewを使用する1
C# TreeViewを使用する1C# TreeViewを使用する1
C# TreeViewを使用する1
 
Word bench nagoya 5月度
Word bench nagoya 5月度Word bench nagoya 5月度
Word bench nagoya 5月度
 
C#によるファイルの読み書き
C#によるファイルの読み書きC#によるファイルの読み書き
C#によるファイルの読み書き
 
C# Database操作1 接続と切断-
C# Database操作1  接続と切断-C# Database操作1  接続と切断-
C# Database操作1 接続と切断-
 
C# FileSystemWatcherコントロールを使用したアプリケーションの作成
C# FileSystemWatcherコントロールを使用したアプリケーションの作成C# FileSystemWatcherコントロールを使用したアプリケーションの作成
C# FileSystemWatcherコントロールを使用したアプリケーションの作成
 
C# Database操作2 データの取得-
C# Database操作2  データの取得-C# Database操作2  データの取得-
C# Database操作2 データの取得-
 
C# TreeViewを使用する2
C# TreeViewを使用する2C# TreeViewを使用する2
C# TreeViewを使用する2
 
XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」
XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」
XP祭り関西2011講演資料「Agile開発のスケールアップ~Agile2.0を支えるチケット駆動開発」
 
Bodlogiin code
Bodlogiin codeBodlogiin code
Bodlogiin code
 
Photoshopでバナー "いい感じ" に制作せよ!
Photoshopでバナー "いい感じ" に制作せよ!Photoshopでバナー "いい感じ" に制作せよ!
Photoshopでバナー "いい感じ" に制作せよ!
 
12 分くらいで知るLuaVM
12 分くらいで知るLuaVM12 分くらいで知るLuaVM
12 分くらいで知るLuaVM
 

Similar to C#/.NETがやっていること 第二版

Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crfShuyo Nakatani
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースHajime Yanagawa
 
実録!Railsのはまりポイント10選
実録!Railsのはまりポイント10選実録!Railsのはまりポイント10選
実録!Railsのはまりポイント10選Drecom Co., Ltd.
 
Awsデータレイク事例祭り dmm.com YUKI SASITO.pdf
Awsデータレイク事例祭り dmm.com YUKI SASITO.pdfAwsデータレイク事例祭り dmm.com YUKI SASITO.pdf
Awsデータレイク事例祭り dmm.com YUKI SASITO.pdfYUKI SAITO
 
大規模なJavaScript開発の話
大規模なJavaScript開発の話大規模なJavaScript開発の話
大規模なJavaScript開発の話terurou
 
MySQL Casual Talks Vol.3 LT
MySQL Casual Talks Vol.3 LTMySQL Casual Talks Vol.3 LT
MySQL Casual Talks Vol.3 LTTomohiro Ikeda
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とToru Takahashi
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とToru Takahashi
 
Git & GitHub & kintone でウルトラハッピー!
Git & GitHub & kintone でウルトラハッピー!Git & GitHub & kintone でウルトラハッピー!
Git & GitHub & kintone でウルトラハッピー!ymmt
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)信之 岩永
 
Fabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFesFabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFesSho Shimauchi
 
Rubyを使った分散全文検索ミドルウェア
Rubyを使った分散全文検索ミドルウェアRubyを使った分散全文検索ミドルウェア
Rubyを使った分散全文検索ミドルウェアKouhei Sutou
 
スマートフォン対応、気をつけたいトラブル
スマートフォン対応、気をつけたいトラブルスマートフォン対応、気をつけたいトラブル
スマートフォン対応、気をつけたいトラブルHiroaki Wakamatsu
 

Similar to C#/.NETがやっていること 第二版 (20)

Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crf
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
実録!Railsのはまりポイント10選
実録!Railsのはまりポイント10選実録!Railsのはまりポイント10選
実録!Railsのはまりポイント10選
 
Awsデータレイク事例祭り dmm.com YUKI SASITO.pdf
Awsデータレイク事例祭り dmm.com YUKI SASITO.pdfAwsデータレイク事例祭り dmm.com YUKI SASITO.pdf
Awsデータレイク事例祭り dmm.com YUKI SASITO.pdf
 
大規模なJavaScript開発の話
大規模なJavaScript開発の話大規模なJavaScript開発の話
大規模なJavaScript開発の話
 
Zabbix study5lt
Zabbix study5ltZabbix study5lt
Zabbix study5lt
 
MySQL Casual Talks Vol.3 LT
MySQL Casual Talks Vol.3 LTMySQL Casual Talks Vol.3 LT
MySQL Casual Talks Vol.3 LT
 
つぶLT20121215
つぶLT20121215つぶLT20121215
つぶLT20121215
 
Tdd
TddTdd
Tdd
 
Tr18015
Tr18015Tr18015
Tr18015
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
EmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤とEmbulkとDigdagとデータ分析基盤と
EmbulkとDigdagとデータ分析基盤と
 
Git & GitHub & kintone でウルトラハッピー!
Git & GitHub & kintone でウルトラハッピー!Git & GitHub & kintone でウルトラハッピー!
Git & GitHub & kintone でウルトラハッピー!
 
インフラの話
インフラの話インフラの話
インフラの話
 
ゆるかわPhp
ゆるかわPhpゆるかわPhp
ゆるかわPhp
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
 
Fabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFesFabric + Amazon EC2で快適サポート生活 #PyFes
Fabric + Amazon EC2で快適サポート生活 #PyFes
 
JavaScript 研修
JavaScript 研修JavaScript 研修
JavaScript 研修
 
Rubyを使った分散全文検索ミドルウェア
Rubyを使った分散全文検索ミドルウェアRubyを使った分散全文検索ミドルウェア
Rubyを使った分散全文検索ミドルウェア
 
スマートフォン対応、気をつけたいトラブル
スマートフォン対応、気をつけたいトラブルスマートフォン対応、気をつけたいトラブル
スマートフォン対応、気をつけたいトラブル
 

More from 信之 岩永

YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話信之 岩永
 
C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話信之 岩永
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理信之 岩永
 
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリームC# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム信之 岩永
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型信之 岩永
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ信之 岩永
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方信之 岩永
 
Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6信之 岩永
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform信之 岩永
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014信之 岩永
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎信之 岩永
 
プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版信之 岩永
 
Anders Hejlsberg Q & A
Anders Hejlsberg Q & AAnders Hejlsberg Q & A
Anders Hejlsberg Q & A信之 岩永
 
C#マスコット(公開用)
C#マスコット(公開用)C#マスコット(公開用)
C#マスコット(公開用)信之 岩永
 

More from 信之 岩永 (19)

YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話YouTube ライブ配信するようになった話
YouTube ライブ配信するようになった話
 
C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0C# 9.0 / .NET 5.0
C# 9.0 / .NET 5.0
 
C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話C# コンパイラーの書き換え作業の話
C# コンパイラーの書き換え作業の話
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理
 
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリームC# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 
C#言語機能の作り方
C#言語機能の作り方C#言語機能の作り方
C#言語機能の作り方
 
Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6Unityで使える C# 6.0~と .NET 4.6
Unityで使える C# 6.0~と .NET 4.6
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014
 
Coding Interview
Coding InterviewCoding Interview
Coding Interview
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 
プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版プログラミング .NET Framework 第4版
プログラミング .NET Framework 第4版
 
Anders Hejlsberg Q & A
Anders Hejlsberg Q & AAnders Hejlsberg Q & A
Anders Hejlsberg Q & A
 
C#マスコット(公開用)
C#マスコット(公開用)C#マスコット(公開用)
C#マスコット(公開用)
 
広がる .Net
広がる .Net広がる .Net
広がる .Net
 

Recently uploaded

スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 

Recently uploaded (9)

スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 

C#/.NETがやっていること 第二版