C#

SharpLabでC#の内部動作を確認する

SharpLabは、自分が書いたC#のコードが内部的にどのように動作しているのかを確認できるWebサービスです。インターネットに接続できる環境であれば、ブラウザだけでどこからでも利用できます。

SharpLabへのアクセス

ブラウザのアドレスバーに次のURLを入力してアクセスします。

https://sharplab.io/

図1: ブラウザのアドレスバーに「https://sharplab.io/」を入力してアクセスする

画面の構成

アクセスすると、次のような画面が表示されます。画面左側にC#のコードを記述すると、右側にそのコードが内部的にどのように変換されて動作しているかがリアルタイムに表示されます。初期状態では、次のような単純なクラスのコードがサンプルとして入力されています。

図2: SharpLabの初期画面。左側がC#のコード、右側が内部的な変換結果

それでは実際に、自分でコードを書いて内部動作を確認してみましょう。

usingステートメントの内部動作を確認する

例として、ファイルを読み込むコードを書いてみます。左側のコード欄に、次のコードを入力します。

using System.IO;
using (var stream = File.OpenRead("test.txt"))
{

}

 

ここでポイントになるのが、1行目の using System.IO; です。これを書かずに File.OpenRead(…) とだけ書くと、File という識別子が見つからずコンパイルエラーになります。using System.IO; を書いて名前空間を取り込むか、次の図のように System.IO.File.OpenRead(…) と完全修飾名で書くか、どちらかが必要です。

図3: using System.IO; を使わず、System.IO.File.OpenRead(…) と完全修飾名で書いても同じ結果になる(グレー表示のusingは不要になったことを示す)

このコードを書くと、右側の Results 欄に、内部的な変換結果(デコンパイル結果)が表示されます。

図4: usingステートメントの変換結果。try-finallyブロックに変換され、finally句の中で確実にDispose()が呼ばれていることがわかる

右側に表示された結果を、実際のC#コードとして書き起こすと次のようになります。

FileStream fileStream = File.OpenRead("test.txt");

try
{
}
finally
{
  if (fileStream != null)
  {
    ((IDisposable)fileStream).Dispose();
  }
}

このように、usingステートメントは内部的にはtry-finallyブロックに変換されており、finally句の中で必ずDispose()が呼び出されていることが確認できます。usingを使えば例外が発生した場合でもリソースが確実に解放されるということを、内部動作のレベルで裏付けを持って理解できます。

foreachステートメントの内部動作を確認する

同様に、foreachステートメントについても内部動作を確認してみます。List<int>のようなジェネリックコレクションを使う場合は、System.Collections.Genericのusingディレクティブが必要になります。usingが無い状態でList<int>と入力すると、次の図のようにインテリセンスの候補からusingディレクティブを追加できます。

図5: List<int>を使うと、インテリセンスの候補から using System.Collections.Generic; を追加できる

using を追加したうえで、次のようにforeachのコードを書きます。

using System.Collections.Generic;
using System.IO;

var l = new List<int>();
foreach (var val in l)
{
}

このコードを書くと、右側に次のような変換結果が表示されます。

図6: foreachの変換結果。GetEnumerator()でEnumeratorを取得し、while(enumerator.MoveNext())でループしながら、finally句で確実にDispose()している

右側に表示された結果を、実際のC#コードとして書き起こすと次のようになります。

List<int> list = new List<int>();
List<int>.Enumerator enumerator = list.GetEnumerator();
try
{
  while (enumerator.MoveNext())
  {
    int current = enumerator.Current;
  }
}
finally
{
  ((IDisposable)enumerator).Dispose();
}

foreachもまた、内部的にはGetEnumerator()でEnumeratorを取得したうえでtry-finallyブロックに変換されており、ループが終わった後にEnumeratorのDispose()が確実に呼び出されていることがわかります。

まとめ

このように、SharpLabを使うと、自分が書いたコードが内部的にどのように変換され、どのように動作しているかをその場で確認できます。今回確認したusingステートメントやforeachステートメントのように、C#の言語機能が裏側でどのように実装されているかを理解しておくと、自信を持ってコーディングできるようになります。書き方に迷ったときや動作を正確に把握したいときは、ぜひSharpLabで調べてみてください。

C#

■非公開コース「C#14新機能」プレゼント:
非公開コース「C#14新機能」(80分)をご覧になりたい方は
こちらからURLとパスワードを発行していますので、ご覧になってみてください。
非公開コース「C#14新機能」を観る

参考にした書籍

実戦で役立つ C#プログラミングのイディオム/定石&パターン
プログラミングC# 第8版

オブジェクト指向
ジャイルソフトウェア開発の奥義 第2版 オブジェクト指向開発の神髄と匠の技
  すばらしい本です。オブジェクト指向が詰まっています。

オブジェクト脳のつくり方―Java・UML・EJBをマスターするための究極の基礎講座
  サンプルコードはjavaですが,最初にオブジェクト指向に目覚めるのに最適な本です。

Head Firstオブジェクト指向分析設計 ―頭とからだで覚えるオブジェクト指向の基本
  マンガみたいな感じで読めて,オブジェクト指向について学べます。  

Clean Code アジャイルソフトウェア達人の技
Clean Architecture 達人に学ぶソフトウェアの構造と設計
Adaptive Code ~ C#実践開発手法
.NETのエンタープライズアプリケーションアーキテクチャ
実装パターン
  廃盤のため異常に高くなりすぎなので,様子を見た方がいい気がします。一万円のボリュームがあるかどうかは微妙です。

オブジェクト指向でなぜつくるのか
レガシーコード改善ガイド
リファクタリング 既存のコードを安全に改善する

デザインパターン
オブジェクト指向における再利用のためのデザインパターン
オブジェクト指向のこころ
Head Firstデザインパターン ―頭とからだで覚えるデザインパターンの基本

ドメイン駆動開発
エリック・エヴァンスのドメイン駆動設計
実践ドメイン駆動設計
ドメイン駆動
現場で役立つシステム設計の原則
エンタープライズアプリケーションアーキテクチャパターン