2006-05-10 (Wed)

* 現在実行中のメソッド名を取得する MethodBase.GetCurrentMethod()

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

.NET で現在実行中のメソッド名を取得するには、System.Reflection.MethodBase.GetCurrentMethod().Name を使う。

- トレース出力のために現在実行中のメソッド名を取得したい

アプリケーションの実行状態の追跡のため、メソッドの頭でメソッド名やそのときの時刻などをトレース出力したい。

トレースしたいメソッドが3個くらいしかなければ、以下のようにメソッド名を直書きしてもいいけど、タイプミスしたり、リファクタリングしてメソッド名が変わったときに修正する手間がかかってしまうのは困る。

Trace.WriteLine(DateTime.Now.ToString() + " PlayVideoClip");

メソッド名はリフレクションを使って取得できるので、とりあえず System.Reflection.MethodBase.GetCurrentMethod().Name を使うことにした。

Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

using System.Reflection; しておけば MethodBase.GetCurrentMethod().Name で済むけど、トレースしたいところにペタペタとコピー & ペーストすることを考えて、完全な名前で書いた。

うーん。でも、そもそもこれをコピー & ペーストする手間が煩雑で困るな。今回はこれで良かったけど、今後もコピペを繰り返すのは美しくないなあ。

メソッドにコンストラクタやデストラクタみたいな仕組みがあって、そこでトレース出力できるといいのに。ASP.NET のパイプライン処理モデルみたいな仕組みがメソッド自体に備わってるような感じ。ちょっと仕組みが大げさだから無いような気もするけど、調べてみよう。

2006-05-07 (Sun)

* アプリケーションを終了させるには Environment.Exit()

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

C# でアプリケーションを終了させるには System.Environment.Exit() を使う。

Environment.Exit(0);

Exit メソッドの引数にアプリケーションの終了コードを指定できる。これは 2005-01-20 「C# でアプリケーションの終了コードを返す」でも書いた。正常終了なら 0 を指定するのが慣例。それ以外の場合はアプリケーションの作りによって値の使い方は千差万別。呼び出し側にエラーを伝えるために、エラーに応じて細かく番号を決めておくこともある。一方、エラーはみんな終了コード1と割り切って定義することもある。

System.Windows.Forms.Application.Exit() というのもあるが、これはメッセージループを止めるだけでそれ以外の処理は続行してしまう。

今回はこれに関する失敗をした。業務エラー発生時にダイアログを出して WinForm アプリケーションを終わらせようとしたけど、Application.Exit() を使ってしまったために処理が続行されてしまった。テストしてすぐに気づいたけどね。

2006-05-03 (Wed)

* C# と DirectX で動画を再生する

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#] [Windows]

2006-04-27 「C# でスクリーンセーバーを作る」の続き。C# から DirectX を使って MPEG2 の動画を再生する。

- DirectX SDK のダウンロード

動画再生部分は DirectX を使って作ることにしたので、DirectX SDK をダウンロードした。サイズが390.2MB もあるので、気長に。

DirectX SDK - (April 2006)
http://www.microsoft.com/downloads/details.aspx?FamilyId=7AB ...

ダウンロードしたファイルを実行。インストーラではいつも通り「次へ」を連打してインストール完了。

- Microsoft.DirectX.AudioVideoPlayback で動画を再生

動画再生部分は Microsoft.DirectX.AudioVideoPlayback を使って簡単に作れた。

string path = GetNextClipPath();
fileIndex++;
if (videoClip == null) {
    videoClip = new Video(path);
} else {
    videoClip.Ending -= this.ClipEnded;
    videoClip.Open(path);
}
videoClip.Ending += new System.EventHandler(this.ClipEnded);
videoClip.Owner = this;
videoClip.Fullscreen = false;
Bounds = new Rectangle(0, 20, 1280, 960);
videoClip.Play();

これをベースとしている Visual Studio 2005 のスクリーンセーバースタートキットに組み込めば、動画を再生するスクリーンセーバーのできあがり。とっても簡単だ。

プログラムに名前を付けよう。スタートキットがデフォルトで付ける ScreenSaver1.exe だと味気ないし、「画面のプロパティ」で選択するときも何か名前が表示されてほしいし。とくに思いつかなかったので、とりあえず SaveTheQueen (セーブザクイーン) にした。FF12 に出てきた剣の名前が元ねただ。FF9 にも出てきたかな? もともと 2006-04-20 の「FF12 のムービーをリッピング (ripping) して再生」でリップしたファイルを再生するスクリーンセーバーを作るのが目的だから、save という単語が入っていて、FF っぽい名前であればなんでも良かった。

- SaveTheQueen のソース

後の私も含めて、誰かの参考になるかもしれないので、メインフォームとオプションフォームのコードを全部載せておく。私の環境以外を考慮していないコードだし、エラー処理やオプションの処理も入ってない。たとえばビデオクリップのパスに対して FileExists() もしてない。

ソース一式とバイナリをパッケージしたものはそのうち作ろうかな。Suversion から 自動でチェックアウトしてビルドして ClickOnce としてパッケージするようにしよう。

ScreenSaverForm.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Microsoft.DirectX.AudioVideoPlayback;

namespace SaveTheQueen {
    partial class ScreenSaverForm : Form {

        private bool isActive = false;
        private Point mouseLocation;
        private Video videoClip;
        private DefaultTraceListener dtl;

        /// <summary>
        /// 再生するリスト上の現在位置。始点は0。
        /// </summary>
        private int fileIndex = 0;

        public ScreenSaverForm() {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            dtl = (DefaultTraceListener)Trace.Listeners["Default"];
            dtl.LogFileName = @"c:\trace.txt";

            InitializeComponent();
            SetupScreenSaver();
            PlayVideoClip();
        }

        private void SetupScreenSaver() {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            // ダブル バッファを使用して、表示パフォーマンスを改善します。
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);

            // マウスをキャプチャします。
            this.Capture = true;

            // アプリケーションを全画面表示モードに設定して、マウスを表示しません。
            Cursor.Hide();
            // Bounds = Screen.PrimaryScreen.Bounds;
            ShowInTaskbar = false;
            DoubleBuffered = true;

            ResumeVideoClip();
        }

        /// <summary>
        /// 現在再生しているビデオクリップの情報を保存します。
        /// </summary>
        private void SaveVideoClip() {
            Properties.Settings.Default.LastClipIndex = fileIndex - 1;
            Properties.Settings.Default.LastClipPosision = videoClip.CurrentPosition;
            Properties.Settings.Default.Save();
        }

        /// <summary>
        /// 前回終了時に再生していたビデオクリップの情報を復元します。
        /// </summary>
        private void ResumeVideoClip() {
            int lastClipIndex = Properties.Settings.Default.LastClipIndex;
            if (0 <= lastClipIndex && lastClipIndex < Properties.Settings.Default.videoClipPath.Length) {
                fileIndex = lastClipIndex;
            }
      }

        private void PlayVideoClip() {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name );

            string path = GetNextClipPath();
            fileIndex++;
            if (videoClip == null) {
                videoClip = new Video(path);
            } else {
                videoClip.Ending -= this.ClipEnded;
                videoClip.Open(path);
            }
            videoClip.Ending += new System.EventHandler(this.ClipEnded);
            videoClip.Owner = this;
            videoClip.Fullscreen = false;
            // WindowState = FormWindowState.Normal;
            Bounds = new Rectangle(0, 20, 1280, 960);
            videoClip.Play();
        }

        private void ClipEnded(object sender, System.EventArgs e) {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            PlayVideoClip();
        }

        private string GetNextClipPath() {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            if (Properties.Settings.Default.videoClipPath.Length == 0) {
                return "";
            }
            if (Properties.Settings.Default.videoClipPath.Length - 1 < fileIndex) {
                fileIndex = 0;
            }
            if (fileIndex < 0) {
                fileIndex = Properties.Settings.Default.videoClipPath.Length - 1;
            }

            string path = Properties.Settings.Default.videoClipPath[fileIndex];
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name + " " + path);

            return path;
        }

        private void ScreenSaverForm_MouseMove(object sender, MouseEventArgs e) {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            // IsActive および MouseLocation を、このイベントが最初に呼び出されるときにのみ設定します。
            if (!isActive) {
                mouseLocation = MousePosition;
                isActive = true;
            } else {
                // 最初の呼び出し以来マウスが著しく移動した場合、閉じます。
                if ((Math.Abs(MousePosition.X - mouseLocation.X) > 10) ||
                    (Math.Abs(MousePosition.Y - mouseLocation.Y) > 10)) {
                    Close();
                }
            }
        }

        private void ScreenSaverForm_KeyDown(object sender, KeyEventArgs e) {
            Trace.WriteLine(DateTime.Now.ToString() + System.Reflection.MethodBase.GetCurrentMethod().Name);

            if (e.KeyData == Keys.F) {
                // 次のクリップ
                PlayVideoClip();
            } else if (e.KeyData == Keys.B) {
                // 前のクリップ
                fileIndex -= 2;
                PlayVideoClip();
            } else if (e.KeyData == Keys.R) {
                // 現在再生中のクリップを頭からもう一度再生
                fileIndex--;
                PlayVideoClip();
            } else {
                Close();
            }
        }

        private void ScreenSaverForm_MouseDown(object sender, MouseEventArgs e) {
            Trace.WriteLine(DateTime.Now.ToString() + System.Reflection.MethodBase.GetCurrentMethod().Name);

            Close();
        }

        private void ScreenSaverForm_FormClosing(object sender, FormClosingEventArgs e) {
            Trace.WriteLine(DateTime.Now.ToString() + " " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            if (videoClip != null) {
                SaveVideoClip();
                videoClip.Dispose();
                videoClip = null;
            }
        }
    }
}

ダブルバッファなどはベースとしたスクリーンセーバースタートキットに最初から入ってたもの。効果のほどは不明。コメントアウトしても問題なく再生できてたし。CPU 負荷や GPU の負荷が違うのかな。タスクマネージャで見てたけど、コメントアウトしても負荷が十分に低かったので違いがわからなかった。

OptionsForm.cs
using System;
using System.Configuration;
using System.Drawing;
using System.Windows.Forms;


namespace SaveTheQueen {
    partial class OptionsForm : Form {
        public OptionsForm() {
            InitializeComponent();

            // 現在の設定からテキスト ボックスを読み込みます。
            try {
                backgroundImageFolderTextBox.Lines = Properties.Settings.Default.videoClipPath;
            //  rssFeedTextBox.Text = Properties.Settings.Default.RssFeedUri;
            } catch {
                MessageBox.Show("スクリーン セーバーの設定での読み取り中に問題が発生しました。");
            }
        }

        // [適用] ボタンが最後に押されてから変更が行われた場合にのみ、
        // [適用] ボタンをアクティブな状態に更新します。
        private void UpdateApply() {
            /*
            if (Properties.Settings.Default.BackgroundImagePath != backgroundImageFolderTextBox.Text
                  || Properties.Settings.Default.RssFeedUri != rssFeedTextBox.Text)
                applyButton.Enabled = true;
            else
                applyButton.Enabled = false;
            */
        }

        // [適用] ボタンが最後に押されてからの、すべての変更を適用します。
        private void ApplyChanges() {
            Properties.Settings.Default.videoClipPath = backgroundImageFolderTextBox.Lines;
            Properties.Settings.Default.Save();
        }

        private void btnOK_Click(object sender, EventArgs e) {
            try {
                ApplyChanges();
            } catch (ConfigurationException) {
                MessageBox.Show("設定を保存できませんでした。スクリーン セーバーと同じディレクトリ内に .config ファイルがあることを確認してください。", "設定を保存できませんでした。", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } finally {
                Close();
            }
        }

        private void btnCancel_Click(object sender, EventArgs e) {
            Close();
        }

        private void btnApply_Click(object sender, EventArgs e) {
            ApplyChanges();
            applyButton.Enabled = false;
        }

        // ユーザー指定された URI が有効な RSS フィードにポイントするかどうかを確認します。
        private void validateButton_Click(object sender, EventArgs e) {
            try {
                // RssFeed.FromUri(rssFeedTextBox.Text);
            } catch {
                MessageBox.Show("有効な RSS フィードではありません。", "有効な RSS フィードではありません。", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            MessageBox.Show("有効な RSS フィードです。", "有効な RSS フィードです。", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        private void browseButton_Click(object sender, EventArgs e) {
            // [ファイルを開く] ダイアログを開いて、イメージを選択します。

            DialogResult result = backgroundImageFolderBrowser.ShowDialog();
            if (result == DialogResult.OK) {
                backgroundImageFolderTextBox.Text = backgroundImageFolderBrowser.SelectedPath;
                UpdateApply();
            }
        }

        private void rssFeedTextBox_TextChanged(object sender, EventArgs e) {
            UpdateApply();
        }

        private void backgroundImageFolderTextBox_TextChanged(object sender, EventArgs e) {
            UpdateApply();
        }

        private void backgroundImageOpenFileDialog_FileOk(object sender, System.ComponentModel.CancelEventArgs e) {

        }

        private void backgroundImageFolderBrowser_HelpRequest(object sender, EventArgs e) {

        }

        private void button1_Click(object sender, EventArgs e) {
            DialogResult result = videClipOpenFileDialog.ShowDialog();
            if (result == DialogResult.OK) {
                backgroundImageFolderTextBox.Lines = videClipOpenFileDialog.FileNames;
                UpdateApply();
            }
        }

        private void rssGroupBox_Enter(object sender, EventArgs e) {

        }
    }
}

OptionsForm.cs は不要なコードを消してないので冗長。

C#でムービースクリーンセーバー
http://d.hatena.ne.jp/bellbind/20060428/1146200768
ムービースクリーンセーバーを作ったってはなしだけど、作るのに必要な情報は入って無いんで自分で調べて書いてみた。

  public SimpleScreenSaver() {
    this.FormBorderStyle = FormBorderStyle.None;
    this.WindowState = FormWindowState.Maximized;
    this.KeyDown += new KeyEventHandler(this.MyKeyDown);
    this.MouseDown += new MouseEventHandler(this.MyMouseDown);
    this.Load += new EventHandler(this.MyLoad);
    this.ClientSize = new Size(640, 480);
    this.player = new Video("movie.avi");
    this.player.Owner = this;
  }

(略)

cscでのビルドには/r:Microsoft.DirectX.AudioVideoPlayback.dllが必要だけど、これはc:\WINDOWS\Microsoft.NET\DirectX for Managed Code\*\以下にあるのでそれを使う。

私もとりえあず再生さえできれば良かったので AudioVideoPlayback を使いました。

あれ? もしかして DirectX の dll って最初からインストールされてたのかな? わざわざ SDK をダウンロードする必要ってなかった? まあ、スクリーンセーバーを作るためだけにわざわざ Visual Studio 2005 をインストールしてるわけだから、DirextX SDK を追加で入れるくらい誤差みたいなものということで。それにそもそも .NET Framework 2.0 をインストールする必要がある。スクリーンセーバーのためだけに .NET Framework 2.0 を要求するって結構すごいよなあ。

本当はもっといろいろ DirectX の機能を使ってみようかと思った。ビデオクリップの解像度にあわせてディスプレイの解像度を変更したり、マルチディスプレイ環境では再生するディスプレイを選択できるようにしたりとかね。でも、結局液晶ディスプレイで再生してるので、解像度を落としても dot-by-dot で再生できるわけじゃなく、スケーリングが入るので美しさは変わらない。高い解像度のままでも CPU や GPU の負荷もとくに問題にならなかった。マルチディスプレイ対応については、「あったらいいな」くらいで必須じゃない。というわけで今の私の環境ではあんまり意味がなくなったので見送った。

2006-04-27 (Thu)

* C# でスクリーンセーバーを作る

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#] [Windows]

Visual Studio 2005 Express Edition を使ってスクリーンセーバーを作る。

2006-04-25 で Visual Studio 2005 (VS2005) のインストールも終わった。VS2005 をインストールした理由の「作りたかったちょっとしたアプリケーション」とはスクリーンセーバーだ。2006-04-20 の「FF12 のムービーをリッピング (ripping) して再生」でリッピングした MPEG2 ムービーを再生するスクリーンセーバーを作りたい。そういうスクリーンセーバーはすでにいくつかあるが、やっぱり自分好みのものがほしい。

VS2005 に慣れるにはいい題材かな・・・と思ったら、そもそも VS2005 のプロジェクトテンプレートとして「スクリーンセーバースタートキット」というのがあるじゃん。これはラッキー。とりあえずこれを見てみよう。

スクリーンセーバースタートキット

このスタート キット プロジェクトでは、RSS フィードからのニュース記事を表示するスクリーン セーバーの構築方法を紹介します。

- スクリーンセーバースタートキット

スクリーンセーバーの実体は単なる実行ファイルと聞いたことがあったが、その通りだった。いくつかの引数を処理できる実行ファイルを作り、拡張子を exe から scr に変更して windows ディレクトリに配置すれば、「画面のプロパティ」などからスクリーンセーバーとして設定できる。

スクリーンセーバースタートキットには、そういった実行ファイルを作るために必要なもの一式が入っている。メインフォーム一つ、設定用のオプションフォーム一つ、エントリポイント (アプリケーションの開始点) の C# ソースファイルが一つ、あとはライブラリとリソース群。

以下はエントリポイント。Program.cs に書かれている。

static void Main(string[] args) {
    if (args.Length > 0) {
        // 2 文字のコマンド ライン引数を取得します。
        string arg = args[0].ToLower(CultureInfo.InvariantCulture).Trim().Substring(0, 2);
        switch (arg) {
            case "/c":
                // オプション ダイアログを表示します。
                ShowOptions();
                break;
            case "/p":
                // プレビューに対して何もしません。
                break;
            case "/s":
                // スクリーン セーバーのフォームを表示します。
                ShowScreenSaver();
                break;
            default:
                MessageBox.Show("コマンド ライン引数が無効です :" + arg, "コマンド ライン引数が無効です。", MessageBoxButtons.OK, MessageBoxIcon.Error);
                break;
        }
    } else {
        // 渡される引数がない場合、スクリーン セーバーを表示します。
        ShowScreenSaver();
    }
}

必ず必要な引数の処理などは全部テンプレートに入ってる。いやー楽だ。実際、ビルドしてすぐにスクリーンセーバーとして使える。動作を変えたければ、上記から呼んでいる ShowScreenSaver() にその処理を書けば OK。私の場合、動画を再生するコードを書けばいい。

- C# で動画を再生する

動画を再生するにはいろいろ方法はあると思うが、せっかくだからいままでやったことのない領域でやろうと思う。スクリーンセーバー部分はテンプレート使っちゃってるし。というわけで DirextX を使うことにした。再生するだけなら簡単だった。詳細はまた後ほど。

2006-04-25 (Tue)

* Visual Studio 2005 Express Edition をインストール

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

ちょっとしたアプリケーションを作るため、Visual Studio 2005 が必要になったのでインストール。インストールするマシンはこれで3台目。

- インストーラを使うので ISO イメージのダウンロードは必要なし

いつの間にか直接実行可能なインストーラが Web で公開されるようになっていた。2005-12-16 に書いた「Visual Studio 2005 Express Edition 日本語版ダウンロード」の時点では iso イメージしか公開されていなかったので、ダウンロードした後 CD-R などに焼くか、iso イメージから 仮想 CD-ROM ドライブを生成するツールなどを使う必要があって手間がかかったが、これでかなり楽になった。

Web から直接インストール可能な "Webインストール" の公開を開始いたしました。Visual Basic、Visual C#、Visual C++、Visual Web Developer 各ページの上部にある「Web からインストール」リンクをクリックいただくことで、インストールを開始いただけます。なお、追加の製品ドキュメントを参照する場合は、MSDN Express Library をインストールしてください。

以下の Visual C# 2005 Express Edition 日本語版 をダウンロード。
http://go.microsoft.com/fwlink/?LinkId=51411&clcid=0x411

- Visual Studio 2005 Express Edition をインストール

インストールするにはダウンロードしたファイルを実行するだけ。

インストールする製品 (省略可) を選択してください。
インストール オプション
Microsoft SQL Server 2005 Express Edition x86 (ダウンロード サイズ: 55 MB)
SQL Server Express は、アプリケーション データの読み取り、書き込み、および配置を容易にする Microsoft SQL Server のベーシック バージョンです。


インストールするフォルダ(&I):

C:\Program Files\Microsoft Visual Studio 8\

以下の製品をダウンロードしてインストールします:
  Microsoft .NET Framework 2.0  Microsoft .NET Framework 2.0 日 本 語 Language Pack  Visual C# 2005 Express Edition  Microsoft SQL Server 2005 Express Edition x86
ディスク領域の必要条件: C: 893 MB
ダウンロードサイズの合計: 111 MB
インストールを続行する前にインターネットに接続してください。

SQL Server 2005 などのオプションがあるけど、とりえあえず全部入りで。もっとも、今回はディスクが足りなかったので、ネットワークドライブ上にインストールした。ある意味富豪的だね。

あとは OK や「次へ」を連打していれば、必要なパッケージを勝手にダウンロードしてインストールしてくれる。

Visual C# 2005 Express Edition が正常にインストールされました。最新の Service Pack およびセキュリティ更新プログラムに関しては、Windows Update を参照してください。

これでインストール完了。

- ライセンスキーをもらう

インストールはこれで完了だが、継続的に使用するにはシリアルナンバーというかライセンスキーをもらう必要がある。

30 日以内にソフトウェアの登録を行ってください。

この製品を続けてお使いいただくために、今すぐ登録を行ってください。後からヘルプメニューの [製品の登録] を選択して、登録を行うこともできます。詳細については、登録の利点を参照してください。

以前は無償提供の期間が一年しかないと聞いたので、すぐに登録してライセンスキーをもらった。しかし今となってはもう「ずっと無償」になったわけだから、必要になったときで良いと思う。30日以上使い続けることがわかっていれば登録しても良いけど、今回はせいぜい1週間くらいしか使わないだろうしね。

ちなみに他のマシン用に発行されたライセンスキーを入れてみたけど見事に弾かれた。そりゃそうだよね。マシン固有の値からハッシュしてるだろうし。以前登録したときは MSN パスポートが必要だったりしたので、その手間を省けるならとやってみたけど、そうは問屋が卸しませんでしたとさ。

2006-03-03 (Fri)

* プログラミング C# 第4版を購入した

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [] [C#] [.net]

プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応

ジェシー リバティ / Jesse Liberty / 鈴木 幸敏 / 首藤 一幸 / 情報技研
発売日: 2006/02


amazon で詳しく見る   bk1で詳しく見る

プログラミング C# 第4版を購入。ひとまず全22章中の3章まで読んだ。3章はまだ C# の基礎の部分だが、かなり勉強になる。曖昧な部分が消えていく感じ。「そうなんだ」と発見することもいくつかあり、すでにマーカーや書き込みが10カ所くらい入っている状態。

C と Delphi と JavaScript と Perl と PHP と Ruby と C# のそれぞれの文法や仕様が頭の中でごちゃごちゃになることがある。foreach の書き方とか、ループを途中で脱出するのは last なのか break なのかとか、switch case が使えるのはどれなのかとか、bool 型が使えるのはどれなのかとか、プロパティが使えるのはどれなのかとか。

こんな状況で今後 C# を仕事で使うことに不安を感じてた。とりあえずコードを書くことはできるけど、C# を使いこなせていないので冗長な書き方になったり、コードに曖昧な部分が残ったりしかねない。この本を読むことで、それを解決できそうだ。

言語の基礎を記述している章でさえ「勉強になる」と言ってる状態なんだから、より先の章は推して知るべし。早めに目を通しておこう。

2006-02-20 (Mon)

* ASP.NET で Trace が有効かどうか判定する

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

System.Web.HttpContext.Current.Trace.IsEnabled でトレース自体の有効・無効を判定できる。

- トレース自体が有効かどうかを判定する

ASP.NET にはトレース出力機能がある。prinf デバッグなどと違い、トレースの有効・無効を web.config 等の設定ファイルで一括変更できるため使い勝手がよい。

トレースがオフになっている場合はデータは画面などには出力されない。しかし、取得に時間がかかるデータなどの場合、出力だけでなくトレースに必要なデータのセットアップ自体をしないで欲しいときがある。

System.Web.HttpContext.Current.Trace.IsEnabled にトレース自体の有効・無効がセットされているので、これを判定して Trace を呼び分けてやればよい。

if (HttpContext.Current.Trace.IsEnabled) {
    Tarce.Warn(GetHeavyData());
}

もしくは、コンパイル時の条件変数を使う。ただ、当然ながら有効化にはコンパイルが必要で手間がかかる。 HttpContext.Current.Trace.IsEnabled の方が使い勝手が良い。

#if DEBUG
Tarce.Warn(GetHeavyData());
#endif

via: .NETエンタープライズWebアプリケーション開発技術大全 vol.3 ASP.NET応用 240ページ。

2006-02-10 (Fri)

* Visual Studio スタートページの既存のプロジェクトの表示件数を変える

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

Visual Studio スタートページには、作業したプロジェクトの履歴が表示される。過去のプロジェクトの環境をすぐに復元して作業を始められるので便利。ただ、デフォルトでは4件しか表示されない。これだと圧倒的に足りない。

プロジェクトのファイルはソースコード管理ツール VSS (Visual Source Safe) から取得しているし、その後のソースコード管理はソリューションエクスプローラに任せられるので、ローカルのどこに保存されたかなどはあまり気にしてない。

そのため、4件という履歴の保存件数を超えたプロジェクトを開こうとすると、プロジェクトのローカルのパスや名前を覚えていなければならないので時間がかかる。久しぶりに開くプロジェクトならなおさら。ブックマークしてるけど URL を知らないサイトを検索なしで探すような感じ。

「既存のプロジェクト」の表示件数を変えてもっと大量に表示したい。以下、Visual Studio .NET 2003 での設定方法。

- Visual Studio スタートページの既存のプロジェクトの表示件数を変える

「ツール (T)」 の「オプション (O)」 の「環境」ディレクトリの「全般」を開く。
以下を設定する。

最後に使用した一覧に表示する項目(&Y): 24 項目

99 を入れたら、以下のダイアログが出て拒否された。

Microsoft Development Environment

最後に使用した一覧には 1 - 24 項目まで含めることができます。

仕方ないので24で設定。ヘルプを読んだら以下のようにちゃんと書いてあった。

[最後に使用した一覧に表示する項目]

[ファイル] メニューに表示される、最近使ったプロジェクトとファイルの数をカスタマイズします。1 〜 24 の数値を入力します。既定は 4 です。このオプションを使用すると、最近使用したプロジェクトやファイルを簡単に表示できます。

99くらいは設定させてほしいな。こういうものは可能な限り保存しておくと後で便利だからね。2003-03-31 の「/etc/profile への設定内容」で書いたように、私はシェルのコマンドラインの履歴も10万件保存してる。あとでコマンドを再び使いたいときに非常に楽だ。ケータイの着信履歴もデフォルトで1000件くらい保存しておいてほしいと思う。見られたくないものがあるときは別だけど。

2006-02-07 (Tue)

* VSS でチェックアウト中のファイルを再帰的に一覧表示する

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [VSS] [.net]

ソースコード管理ツール Visual Source Safe (VSS) で、チェックアウト中のファイルを再帰的に一覧表示する方法。

- VSS でチェックアウト中のファイルを再帰的に一覧表示する

Visual Source Safe 6.0d でのやりかた。

表示(V) の検索(S) のチェックアウト ユーザー名で検索(S) を選択。
以下のダイアログに対象ユーザーと表示範囲を設定する。

チェックアウト ユーザー

○ すべてのチェックアウト ファイル(A)
● 特定ユーザーのチェックアウト ファイル(F): [Landscape]

「特定ユーザーのチェックアウト ファイル」を選択する。ユーザーは自分以外でも指定可能。長期休暇に入る予定の人がチェックアウトしっぱなしにしているソースがないか確認するののにも使える。

検索範囲

○ 現在のプロジェクトのみを検索(C)
● 現在のプロジェクトとすべてのサブプロジェクトを検索(S)
○ すべてのプロジェクトを検索(P)

「現在のプロジェクトとすべてのサブプロジェクトを検索」を選択するのがポイント。そうすることで、選択しているディレクトリとそのサブディレクトリを再帰的に検索し、結果を表示してくれるので便利。

- 自分がどのファイルをチェックアウトしているかを把握できてないことが問題

CVS や Subversion では、いわゆる楽観的ロックが一般的。ソースの取得時にはとくにロックを行わず、チェックイン (コミット) 時に競合を検出する方法だ。これなら、自分がどのファイルをローカルに持ってきているかはとくに問題にならない。多数のメンバーが入れ替わり立ち替わり修正を加えていく開発スタイルなら、こちらの方が良いだろう。

しかし、少数の固定的なメンバーしかソースを修正しないなら、チェックアウト時に排他をかけるという、いわゆる悲観的ロックの方がわかりやすく安全だ。ただ、これを使うには、それぞれのメンバーで自分自身がチェックアウトしているファイルを常に把握している必要がある。チェックアウトしっぱなしになっているファイルがあると他のユーザがソースを修正できなくなるので、そのままでは開発に支障をきたすおそれがある。

なぜチェックアウトしっぱなにしてしまうかというと、自分がチェックアウトしていることを忘れてしまうからだ。複数のプロジェクトにまたがる複数のドキュメントを平行して修正していると、結局修正しなかったファイルのチェックアウトを取り消すのを忘れてしまったりする。

そういう意味で、VSS はもっとチェックアウト中のファイルを簡単に把握できるインターフェイスを用意してほしい。今回の方法で調べることはできるのだが、プロジェクトのツリーを選択する度に再帰的に検索を走らせているようで、動作が非常に遅い。ときどき確認するくらいなら良いのだが、常に把握するという要求は満たせない。

リポジトリをネットワーク上に置かなければもっと速いのかもしれないが、複数人で利用するソースコード管理サーバはネットワーク上に置きたい。

2006-02-02 (Thu)

* C# では文字列の比較に Equals を使うな

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

C# では文字列の比較に Equals を使わない方がいい。== を使った方がコンパイラの型チェックの恩恵を受けられるし、間違いを少なくすることができる。

Equals を使うな。使う事を推奨するな。
http://www.ailight.jp/blog/kazuk/archive/2006/01/31/11043.as ...
Equals はタイプセーフではない。このため、型のエラーの発見が遅れる。

例:

int a;
string b;
bool result = a.Equals( b );

int a;
string b;
bool result = (a==b);    // CS0019: 演算子 '==' を 'int' と 'string' 型のオペランドに適用することはできません。

よっぽどの理由が無い限り == で比較せよ。

Visual Studio 2003 環境で試してみた。int 型の 0 と string 型の 0 を比較する。

int i = 0;
string s = "0";

Console.WriteLine(i.ToString() == s);
Console.WriteLine(string.Equals(i.ToString(), s));
Console.WriteLine(string.Equals(i, s));
Console.WriteLine(s.Equals(i));

実行結果。上記コードを書いた「プログラマ」としては、比較結果はすべて True になって欲しいのだが、そうなっていない。

True
True
False
False

string.Equals() メソッドにはオーバーロードがあり、string 型同士を比較するものと、Object 型として比較するものがある。Object 型同士の比較だと int 型のオブジェクトと string 型でのオブジェクトという違いがあるので false になってしまう。

これ、バグの元だなあ。Perl だったら型変換があっても気にしないけど、C# というせっかく型の恩恵を受けられる言語を使ってるんだから、最大限に活用した方がいい。

Equals の方が速いとのことだが、上記の動きを理解した上で、100万回のループの中などの速度が重要な部分で使うならいい。でも、日常的に Equals を使うのは避けた方が間違いを減らせる。「速いらしいから」という理由で Equals を常用していた後輩は、上記の動きを知らなかった。

2006-01-26 (Thu)

* プログラミング C# 第4版

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [] [C#] [.net] [プログラミング]

オライリーのメールマガジンを読んでいたら、プログラミングC# 第4版刊行のお知らせが書かれていた。

プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応プログラミングC#―C#2.0/.NET2.0/Visual Studio2005対応

ジェシー リバティ / Jesse Liberty / 鈴木 幸敏 / 首藤 一幸 / 情報技研
発売日: 2006/02


amazon で詳しく見る   bk1で詳しく見る

Jesse Liberty著 鈴木 幸敏、首藤 一幸、株式会社情報技研 訳
5040円

2006年2月発売予定とのこと。まだ amazon に登録されてないようなのでリンクは張らない。「プログラミングC# 第3版」では開発運用編と言語詳解編として分冊になってたけど、第4版では一冊にまとまったのかな? 原書は644ページもあるし、そうなんだろうな。

そろそろリファレンスとして一冊手元に欲しいな。第3版は仕事場では何人か持っている人がいるのですぐに借りることはできるけど、メモを書き込んだり、マーカーを使ったりできないしね。C# 2.0 に対応してるなら買おう。

Programming C#Programming C#

Jesse Liberty
発売日: 2005/04


amazon で詳しく見る

ちなみに、原書ならば日本の amazon でもすぐに手に入る。

- Programming C# 4th Edition は C#2.0 と Visual Studio 2005 対応

うーん、原書は2005年2月なので C#2.0 は未対応な雰囲気・・・?

oreilly.com -- Online Catalog: Programming C#, Fourth Edition
http://www.oreilly.com/catalog/progcsharp4/
The fourth edition of Programming C#--the top-selling C# book on the market--has been updated to the C# ISO standard as well as changes to Microsoft's implementation of the language. It also provides notes and warnings on C# 1.1 and C# 2.0.

と思ったけど、上記解説によると C#2.0 向けの記述や警告があるとのこと。

amazon に掲載されている第4版の原書の表紙画像の右肩にも 4th Edition Covers C# 2.0, .NET 2.0 & Visual Studio 2005 と書かれてるし、それなら翻訳版も十中八九対応してるでしょう。

via: O'Reilly Japan News 第96号

2006-01-23 (Mon)

* C# の正規表現クラスに複数のオプションを指定する

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [C#] [.net] [Perl]

C# の正規表現クラスに複数のオプションを指定するには、 | で RegexOptions 列挙体の OR を取る。|| ではない。

- 今日の失敗 論理演算子 || を RegexOptions に使おうとした

文字列を強調処理する正規表現を書いていたところ、Regex クラスのコンストラクタに正規表現オプションとして RegexOptions 列挙体を渡すところでコンパイルエラーが出た。

Regex highLight = new Regex(Regex.Escape(keyword), RegexOptions.IgnoreCase || RegexOptions.Multiline);

C:\CSProjects\Prototype\ConsoleApplication1\ConsoleApplication1\Class1.cs(30): 演算子 '||' を 'System.Text.RegularExpressions.RegexOptions' と 'System.Text.RegularExpressions.RegexOptions' 型のオペランドに適用することはできません。

んん? なんでエラーになってるの? .NET というか C# で複数の正規表現オプションを Regex クラスのコンストラクタに渡したいときは、OR を取れば良いんでしょう? かなり前にやった覚えがあるんだけど・・・。

あ、わかった。ビット演算の OR (|) じゃなくて論理演算の OR (||) を使ってる。あはは。これが原因か。以下のように修正して無事コンパイルできた。

Regex highLight = new Regex(Regex.Escape(keyword), RegexOptions.IgnoreCase | RegexOptions.Multiline);

- RegexOptions 列挙体でよく使うもの

ちなみに System.Text.RegularExpressions.RegexOptions 列挙体でよく使うのは以下の3つかな。Perl でも i m s などとして指定してたよね。最初は m と s の違いを実感できなかった。とくに、同時に指定したらどうなるのかがわかりにくかったので、2003-03-25 の「Perl の正規表現のオプション m と s」では 実際にどう使うかをまとめた。

RegexOptions 列挙体 - System.Text.RegularExpressions
http://www.microsoft.com/japan/msdn/library/default.asp?url= ...
IgnoreCase
検索時に大文字と小文字を区別しないことを指定します。

Multiline
複数行モードを指定します。^ と $ の意味を変更して、文字列全体の先頭と末尾だけでなく、任意の行の先頭と末尾にもそれぞれが一致するようにします。

Singleline
単一行モードを指定します。\n 以外の任意の文字ではなく、すべての文字と一致するようにピリオド (.) の意味を変更します。

2006-01-06 (Fri)

* VS.NET の「回復できないビルド エラーです」への対処法

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net]

Visual Studio .NET 2003でプロジェクトをビルドしていると「回復できないビルド エラーです」 というエラーが表示されることがある。これが一度表示されてしまうと、何度リビルドしてもダメ。OS をリブートしてもダメ。

[PRB] セットアップ/デプロイメント プロジェクトをビルドすると "修復できないビルド エラーです。" というエラー メッセージが表示される
http://support.microsoft.com/default.aspx?scid=kb;ja;329214
複数のウィンドウが開いている

この問題を解決するには、いくつかのウィンドウを閉じ、セットアップ プロジェクトのビルドを再度実行します。

なんでそれだけでダメになるかよくわからないけど、ソースを表示しているウインドウを閉じていったら直った。OS をリブートしても同じ数のウインドウを開き直してしまうとダメな模様。

VS.NET はたまにこうやって駄々をこねることがあるようだ。ただ、VS.NET 2002 より VS.NET 2003 の方がそういった意味不明の状態になることは少ないような感じがする。子供も一歳違うだけでかなり行動が変わるが、VS.NET も同じように成長してるんだろうな。

2006-01-05 (Thu)

* IE で ローカル HTML ファイルを使用するとセッション Cookie が失われる

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [IE] [.net]

IE で ローカル HTML ファイルを使用するとセッション Cookie が失われるという問題。問題になるのはブラウザを閉じると消える「セッション Cookie」だけで、有効期限の設定された Cookie なら問題は発生しない。

[IE55][IE6] ローカル HTML ファイルを使用するとセッション Cookie が失われる
http://support.microsoft.com/default.aspx?scid=kb;ja;315713
以下の条件をすべて満たす場合、Internet Explorer で保持するべきはずのセッション cookie が失われます。

・ Internet Explorer 5.5 以降を使用している
・ セッション cookie を使用している(cookie に有効期限が設定されていない)
・ ローカルファイルを使用している (ホームページを c:\homepage.html や \\server\share\homepage.html にしている、file:// で始まる URL を使用している、など)
・ 新しいウィンドウを開く(ウィンドウの数を増やす)ような操作を行っている (window.open や window.showModalDialog で子ウィンドウを開く、リンクを [新しいウィンドウで開く] など)
・ ウィンドウを閉じる(ウィンドウの数を減らす)操作を行った後、残りウィンドウの数が 1 つ(または 0)になった

この IE のバグを回避するため、いろんなプロジェクトでそれぞれ対策を取っていた。UI をデザインする段階で window.open などを使わないようにしたり、Cookie に必ず有効期限をセットするようにして回避したり。ASP.NET で、かつ要件が許すときは、web.config で IsCookieless を True にし、ASP.NET の Session ID をクエリストリングに入れて Cookie を使わないようにして回避したこともあった。

IE6 SP1 で修正済みとのこと。パッチが出てたとは。気づかなかった。

Internet Explorer 6 Service Pack で修正される問題の一覧
http://support.microsoft.com/default.aspx?scid=kb;ja;JP32648 ...
315713 (http://support.microsoft.com/kb/315713) [IE55][IE6] ローカル HTML ファイルを使用するとセッション Cookie が失われる

2005-12-21 (Wed)

* ASP.NET の Session State Server を使う

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net]

ASP.NET のセッションを Session State Server を使って管理するための設定。

Session State Server を使っていれば、web.config 修正などによるアプリケーションリスタートや、プロセスリサイクリングが発生してもセッションが消失しない。また、複数サーバでセッションを共有できるという利点がある。インプロセスのセッション InProc モードと比べると速度的には不利だが、信頼性は大幅に向上する。

- クライアント側の準備

web.config で mode="StateServer" にし、stateConnectionString="" に State Server の ホスト名または IP アドレスと、ポートを記述する。

<!--  セッション状態の設定
      既定では、ASP.NET は Cookie を使用して、要求がどのセッションに属するかを識別します。
      Cookie が使用できない場合は、URL にセッション識別子を入力することで、セッションを見つけることができます。
      Cookie を有効にするには、sessionState を cookieless="false" に設定してください。
-->
<sessionState
        mode="StateServer"
        stateConnectionString="tcpip=landscape.sonic64.com:42424"
        sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
        cookieless="false"
        timeout="20"
/>

timeout 属性は分単位なので、上記設定だとセッションの有効期限は20分。

- サーバ側の準備

レジストリを修正して AllowRemoteConnection に 1 を設定する。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters]
"AllowRemoteConnection"=dword:00000001

設定しないと呼び出し側で以下のエラーメッセージが出る。

セッション状態要求をセッション状態サーバーに対して作成できませんでした。ASP.NET 状態サービスが開始されていて、クライアントとサーバーのポートが同じであることを確認してください。サーバーがリモート コンピュータ上にある場合、HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection の値を調べて、このコンピュータがリモート要求を受け付けることを確認してください。

ASP.NET State Service を起動。サービスとして動作するので、自動で起動するように設定しておくのがよい。

イベントの種類:    情報
イベント ソース:    ASP.NET 1.1.4322.0
イベント カテゴリ:    なし
イベント ID:    1076
日付:        2005/12/21
時刻:        12:14:52
ユーザー:        N/A
コンピュータ:    landscape
説明:
状態サーバーは、3 リスナーで受け付けを開始します。

Windows 2003 などであれば、OS のファイアウォール許可設定で TCP 42424 を許可するのも忘れずに。

これだけ。超簡単。

2005-12-16 (Fri)

* Visual Studio 2005 Express Edition 日本語版ダウンロード

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

とうとう Visual Studio 2005 の Express Edition 日本語版のダウンロードができるようになった。

公開されているのは iso イメージなので、インストールはちょっと面倒。Daemon Tools などの CD-ROM 仮想マウントツールがあると便利。

Visual C# 2005 Express Edition 日本語版
http://www.microsoft.com/japan/msdn/vstudio/express/vcsharp/
http://download.microsoft.com/download/9/5/7/9576E49E-1EDA-4 ...
md5: 58e69034c80218893d8e6973e763106c
sha1: db3d0f4d76e6603edd35e75038a5090ec1e25a71
crc32: ce838830

Visual Web Developer 2005 Express Edition 日本語版
http://www.microsoft.com/japan/msdn/vstudio/express/vwd/
http://download.microsoft.com/download/C/E/6/CE6B9F63-0E29-4 ...
crc32: df626aa6

とりあえず Visual C# 2005 Express Edition 日本語版をダウンロードした。Visual Web Developer 2005 Express Edition はしばらく使う機会はないと思う。趣味で ASP.NET のアプリケーションを作っても、公開できるサイトがないから。

- Visual C++ 2005 と Visual Basic 2005 はたぶん使わない

あとはメモだけ。たぶんこれも趣味で使うことはないだろう。

Visual C++ 2005 Express Edition 日本語版
http://www.microsoft.com/japan/msdn/vstudio/express/visualc/
http://download.microsoft.com/download/8/E/8/8E85D539-2255-4 ...
crc32: B3AD1A2F

Visual Basic 2005 Express Edition 日本語版
http://www.microsoft.com/japan/msdn/vstudio/express/vbasic/
http://download.microsoft.com/download/A/B/4/AB4DA3D7-CC3A-4 ...
md5: ef27f47cbcda6daea1473084f7536a3c
sha1: 344c585cb517679b5dd20cfca05bca560e454f41
crc32: 6ee067f9

Visual J# は英語版しかないので省略。

- .NET Framework 2.0 と SDK

.NET Framework 2.0 と SDK も必要なのかな? VS.NET 2003 インストールしたときはどうしてたっけ? とりあえず全部入れておくか。

Download details: .NET Framework Version 2.0 Redistributable Package (x86)
http://www.microsoft.com/downloads/details.aspx?FamilyId=085 ...
http://download.microsoft.com/download/5/6/7/567758a3-759e-4 ...

Microsoft .NET Framework 2.0 日本語 Language Pack (x86)
http://www.microsoft.com/downloads/details.aspx?FamilyID=39c ...
http://download.microsoft.com/download/5/9/4/594a8f51-ba02-4 ...

ダウンロードの詳細 : .NET Framework 2.0 SDK 日本語版 (x86)
http://www.microsoft.com/downloads/details.aspx?FamilyID=FE6 ...
http://download.microsoft.com/download/5/7/2/57246de2-5e4c-4 ...
md5: d41d8cd98f00b204e9800998ecf8427e
sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
crc32: 00000000

- とりあえずダウンロードだけ

とりあえずダウンロードだけした。インストールはまたあとで。

2005-12-13 (Tue)

* MCADもしくはMCSD 取得で赤間さんの本 Vol.1 プレゼント

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [MCP] []

MCAD/MCSD 取得で、赤間さんの本をもらえるキャンペーン中とのこと。

Get MCAD、MCSD キャンペーン!
http://www.microsoft.com/japan/learning/mcp/newgen/upgrade/g ...
新規にMCADもしくはMCSDを取得し、本キャンペーンサイトでお申込いただいた方全員に、企業開発者必携のマイクロソフトプレス刊行技術書籍「.NETエンタープライズWebアプリケーション開発技術大全Vol.1.NET Framework導入編」をもれなくプレゼント

.NETエンタープライズWebアプリケーション開発技術大全〈Vol.1〉.NET Framework導入編.NETエンタープライズWebアプリケーション開発技術大全〈Vol.1〉.NET Framework導入編

赤間 信幸
発売日: 2004/06


amazon で詳しく見る


なんで Vol.1 なのかな。ダブらないようにという親心から出た配慮なのかな? Vol.2 以降は持ってる人多いけど、Vol.1 はその重要性が低く見られてしまっているので持ってる人は少ないだろうし。それとも、Vol.2 以降に比べると値段が手頃なので、プレゼントしても懐は痛まないってこと?

- .NETエンタープライズWebアプリケーション開発技術大全 の略称は?

ところで、「.NETエンタープライズWebアプリケーション開発技術大全」って、略称ないのかな? 「エンタープライズアプリケーションアーキテクチャパターン、原書名 Patterns of Enterprise Application Architecture」 の PofEAA みたいなの。

英語にすると The Complete Developing Technology of .NET Enterprise Web Application かな? これを略すと・・・。 TCDTofNEWA ? わけわかんないし、長すぎて覚えられない。じゃあちょっと短くして、CDofNEW でどう? って、略称以前に、この英語での呼び方、正しいの?

いままで通り「赤間さんの本」って呼ぶのがいいのかなあ・・・。

2005-12-06 (Tue)

* PofEAA エンタープライズ アプリケーションアーキテクチャパターンを購入

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [] [.net]

エンタープライズ アプリケーションアーキテクチャパターンエンタープライズ アプリケーションアーキテクチャパターン

マーチン・ファウラー / 長瀬 嘉秀 / 株式会社 テクノロジックアート
発売日: 2005/04/21


amazon で詳しく見る   bk1で詳しく見る

ファウラーのエンタープライズアプリケーションアーキテクチャパターン、原書名 Patterns of Enterprise Application Architecture (通称 PofEAA) を購入。

6000円とちょっと高めの価格の本だが、私の図書購入予算は十分残っているので気にせず買った。

Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series)Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series)

Martin Fowler / David Rice / Matthew Foemmel / Edward Hieatt / Robert Mee / Randy Stafford
発売日: 2002/11/05


amazon で詳しく見る   bk1で詳しく見る

ちなみに買ったのは邦訳版。黒い表紙の原書の方ではない。翻訳の質があまり良くないらしいが、私の場合は英語よりも日本語の方が早く読めるだろうし、細かい訳や言い回しを追いかけるよりも根源にある思想などをつかむ方が大切だと思い、邦訳版を選んだ。もっとも、あまりに読みにくかったら原書を買ってもいいとは思ってる。

PofEAA はずっと前から読みたいと思っていたんだけど、他にもいろいろ読みたかった本があったりして後回しになっていた。チームのレベルを上げるために設計系の本は一通り読んでおきたいと思ったし、いい機会なので購入。

- 開発における悩み

開発では、どう作ろうかといつも悩む。全体のアーキテクチャはこれでいいのかと悩み、DB のテーブルはこれでいいのかと悩み、クラスの構成はこれでいいのかと悩む。で、これでパフォーマンスに問題がないかと悩み、今後の拡張や仕様変更に強いかどうか悩む。デザインパターンが悩みから解放してくれるんじゃないかと期待した時期もあったが、私の悩みを解決するものでなかった。

結局、すべてを満たす方法はないってことを学んだ。ある設計にはメリットとデメリットがある。現在置かれている状況と、ほんのちょっと先の将来のことを念頭に置いて設計やコーディングするしかないと思った。扱っているビジネスが複雑なんだから、ビジネスロジックやデータ構造が複雑になるのは仕方がないと悟った。悩むのは大切だが、何を切り捨てて何を残したかを明確にしておくことと、とりあえずプロトタイプを作ってみる方が道が開けるということに気づいた。

他の開発者がどう割り切りと妥協をしてどんな設計をしたか。PofEAA を読むことで、そういった設計の思想や試行錯誤に触れられるといいなと思ってる。

- PofEAA の後は何を読もうかな

PofEAA を読み終わってないのに次に読む本を考えるのもどうかと思うが、PofEAA を読んだ後はマイクロソフトコンサルティングファームの赤間さんが書いた「.NETエンタープライズWebアプリケーション開発技術大全」シリーズをもう一度読もうと思っている。今の私は .NET がメインなので、もしかしたら PofEAA よりも赤間さんの本を先に読んだ方がいいかもしれない。

扱っている問題領域も PofEAA より広く、かつ .NET ではどうすればいいかが書かれているという点で実用性が高い。エラー処理やロギングなど、PofEAA が扱わなかった問題についても言及していたはず。その分冊数や分量も多いけど。

Vol.2 のASP.NET基礎編Vol.3 のASP.NET応用編Vol.4 のセキュアアプリケーション設計編はざっと読んだけど、Vol.5 のトランザクション設計編 はまだほんの少ししか読んでない。というのも、去年の年末か今年の初め頃に赤間さんのワークショップを受けたとき、「Vol.5 のトランザクション編はいつ出るんですか?」と聞いたら「もう少しで出ますよ。ちなみに Vol.5 は結構重い内容で、レビューが大変だったんですよ。」といったことを言われて、その言葉が結構重くのしかかり、読み始めるきっかけを失っているからだ。そんなこと気にしないで読めばいいのにね。ちなみに Vol.1 はあんまり必要な気がしなかったので、立ち読みで済ませた。

「.NETエンタープライズWebアプリケーション開発技術大全」が終わった後はデータベース設計系かなあ。データモデリング系の本がいいかな。

追記。
Patterns of Enterprise Application Architecture の略称を PoEAA と書いていたが、PofEAA の方が一般的なようなので修正。PofEAA だと なんかウィザードリィのアイテムの名前みたいだ。「STAFFofGNILDA (ニルダのつえ)」とかね。逆に PoEAA だと PPPoE (PPP over Ethernet) みたいな感じ。

2005-11-30 (Wed)

* C# の StringBuilder と += による文字列連結の速度比較

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

C# で文字列連結するとき、string 型を += で連結するとパフォーマンスが落ちるので、ある程度の回数以上の文字列連結には StringBuilder を使うということが常識となっている。string は不変なので、連結の度に新しいオブジェクトの生成と破棄がおこなわれるからというのが差の発生原因。

ただ、私は実際どの程度性能が劣化するのか計測したことがない。このままだとコードレビューの時に「StringBuilder 使え」と指摘をしても、その根拠となる数値を示せない。後輩などに「計測もしないで性能が落ちるなんて言ってるんですか? 性能を理由にコードを書き換えるときはまず計測しろって言ってたのは斎藤さんじゃないですか?」とか言われかねないので、計測してみる。幸いなことに、私の所にはこの程度の指摘をする必要のある後輩はいないので問題ないけど。

- 計測用コード

傾向がわかればいいので、コードは簡単に書いた。

using System;
using System.Text;

namespace ConsoleApplication1
{
    /// <summary>
    /// Class1 の概要の説明です。
    /// </summary>
    class Class1
    {
        /// <summary>
        /// 文字列連結の速度比較
        /// </summary>
        [STAThread]
        static void Main(string[] args) {

            int times = 100000;
            Console.WriteLine("{0:d} times loop.", times);

            DateTime start_str = DateTime.Now;
            string str = string.Empty;
            for (int i = 0; i < times; i++) {
                str += i.ToString();
            }
            Console.WriteLine("String += : " + (DateTime.Now - start_str).ToString());


            DateTime start_str_builder_default = DateTime.Now;
            System.Text.StringBuilder sb_default = new System.Text.StringBuilder();
            for (int i = 0; i < times; i++) {
                sb_default.Append(i);
            }
            Console.WriteLine("StringBuilder: " + (DateTime.Now - start_str_builder_default).ToString());
        }
    }
}

ちなみに実行環境は以下の通り。
富士通 FMV-E600 Celeron 1.7GHz 512MB Memory
Visual Studio 2003 C# のコンソールアプリケーションとして作成。
Debug モードでコンパイルし、CTRL + F5 で実行。

- 計測結果

計測した結果。times の数を変えて3パターン計測。

1000 times loop.
String += : 00:00:00.0156250
StringBuilder: 00:00:00

千回のループ。StringBuilder を使ったときの所要時間がゼロになってる。このタイマーの精度は 15ミリ秒単位で出力できる程度だっけ? その範囲内に収まっちゃったってことか。何にせよ1000回じゃ少ないなあ。

10000 times loop.
String += : 00:00:01.8125000
StringBuilder: 00:00:00.0156250

一万回のループ。百倍くらい違うな。実際にはいろいろ無茶をやった分に付随するコストも加算されるだろうから、環境によって差は変動するかもしれない。

100000 times loop.
String += : 00:05:20.5000000
StringBuilder: 00:00:00.0781250

十万回のループ。+= の方は耐えられないくらい遅い。指数的に処理時間が増大している。一方、StringBuilder は安定しているな。

これだけ差があれば、StringBuilder 使えという根拠は示せるね。使う基準としては、ループ内だったら迷わず StringBuilder。回数が固定的なループでも、設定の値や仕様が変わってループ回数が変わるのは良くあることだし。ループ外でも回数が多ければ StringBuilder。ループ外で、かつ一桁程度の回数しか連結しないんだったら += でもいい。

ところで、コンパイラは += を StringBuilder に置き換えるという最適化とかしてくれないのかな。この問題については、人間が適切な文字列連結手法を選ぶ方がスマートだと思うけど、コンパイラによる力業で解決できないのかな。

- StringBuilder のキャパシティの初期サイズによる速度の違い

StringBuilder は内部バッファを持っている。扱うデータのおおよそのサイズがあらかじめわかっているなら、そのバッファのキャパシティをコンストラクタに指定しておいた方が、バッファの拡張のオーバーヘッドを抑えられるので速くなるとのこと。これについても計測してみた。

計測に使ったコードは以下の通り。環境は変更なし。
バッファサイズは 1, 8, 64, 256, 1024, 8192, 16384, 65536, 16777216 を試すことにした。この数値の根拠は勘。ちなみに何も指定しない場合のデフォルトは 16 だそうだ。

using System;
using System.Text;

namespace ConsoleApplication1
{
    /// <summary>
    /// Class1 の概要の説明です。
    /// </summary>
    class Class1 {
        /// <summary>
        /// 文字列連結の速度比較
        /// </summary>
        [STAThread]
        static void Main(string[] args) {

            int times = 1000000;
            Console.WriteLine("{0:d} times loop.", times);

            DateTime start_str_builder_default = DateTime.Now;
            System.Text.StringBuilder sb_default = new System.Text.StringBuilder();
            for (int i = 0; i < times; i++) {
                sb_default.Append(i);
            }
            Console.WriteLine("StringBuilder: Capacity: Default: " + (DateTime.Now - start_str_builder_default).ToString());

            int[] capacity_list = {1, 8, 64, 256, 1024, 8192, 16384, 65536, 16777216};
            foreach (int capacity in capacity_list) {
                DateTime start_str_builder = DateTime.Now;
                System.Text.StringBuilder sb = new System.Text.StringBuilder(capacity);
                for (int i = 0; i < times; i++) {
                    sb.Append(i);
                }
                Console.WriteLine("StringBuilder: Capacity: " + capacity.ToString() + " : " + (DateTime.Now - start_str_builder).ToString());
            }
        }
    }
}

1000000 times loop.
StringBuilder: Capacity: Default: 00:00:00.8437500
StringBuilder: Capacity: 1 : 00:00:00.8281250
StringBuilder: Capacity: 8 : 00:00:00.8593750
StringBuilder: Capacity: 64 : 00:00:00.8281250
StringBuilder: Capacity: 256 : 00:00:00.8593750
StringBuilder: Capacity: 1024 : 00:00:00.9375000
StringBuilder: Capacity: 8192 : 00:00:00.8593750
StringBuilder: Capacity: 16384 : 00:00:00.8750000
StringBuilder: Capacity: 65536 : 00:00:00.8593750
StringBuilder: Capacity: 16777216 : 00:00:00.8125000

まずは百万回。うーん、あんまり変わらないね。ほんの少しだけ値が変動してるけど、百分の一秒レベル。F-ZERO でタイムアタックするなら大きな違いだけど、ここではそこまで重要な意味は持っていないと思う。誤差の範囲。

3000000 times loop.
StringBuilder: Capacity: Default: 00:00:02.7031250
StringBuilder: Capacity: 1 : 00:00:02.6562500
StringBuilder: Capacity: 8 : 00:00:02.7968750
StringBuilder: Capacity: 64 : 00:00:02.8437500
StringBuilder: Capacity: 256 : 00:00:02.9687500
StringBuilder: Capacity: 1024 : 00:00:02.8437500
StringBuilder: Capacity: 8192 : 00:00:02.9687500
StringBuilder: Capacity: 16384 : 00:00:02.8593750
StringBuilder: Capacity: 65536 : 00:00:02.9687500
StringBuilder: Capacity: 16777216 : 00:00:02.9062500

三百万回に増やしてもあまり変わらないね。本当はこのあと一千万回も試そうとしたんだけど、512MB のメモリしかない私のマシンではメモリを使い尽くしてスワップが発生し始めたので取りやめた。

キャパシティを指定した場合とそうでない場合で有意な差は見いだせなかった。もちろん、実行環境やデータのサイズによっても変動してくるとは思う。ただ、キャパシティの値はとりあえずデフォルトでも良いかなあ。とにかく += じゃなくて StringBuilder を使う方が大切ってことだな。極限までチューニングする必要があるときは、計測した上でどうするか決めれば良い。でも、そういう時ってたぶん StringBuilder 以外にボトルネックがありそうな気がする。

2005-11-25 (Fri)

* ASP.NET のパイプライン処理と発生するイベント

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net]

HttpApplication オブジェクトから発生するイベントの一覧。

セキュリティ保護された ASP.NET アプリケーションの構築 : 動作のしくみ
http://www.microsoft.com/japan/msdn/net/security/SecNetAP04. ...
各 HTTP モジュールには、これらのイベントをフックするイベント ハンドラを実装できます。

BeginRequest    要求処理の開始前に発生
AuthenticateRequest    呼び出し元を認証
AuthorizeRequest    アクセスチェックを実行
ResolveRequestCache    キャッシュから応答を取得
AcquireRequestState    セッション状態をロード
PreRequestHandlerExecute    要求をハンドラ    オブジェクトに送信する直前に発生
PostRequestHandlerExecute    要求をハンドラ    オブジェクトに送信した直後に発生
ReleaseRequestState    セッション状態を保存
UpdateRequestCache    応答キャッシュを更新
EndRequest    処理の終了後に発生
PreSendRequestHeaders    バッファ内の応答ヘッダーを送信する前に発生
PreSendRequestContent    バッファ内の応答本体を送信する前に発生

2005-11-22 (Tue)

* Visual Studio ユーザーグループ フォーラムの OPML

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [RSS] [.net] [C#]

先日、Visual Studio のユーザーグループ VSUG が発足した。

Visual Studio User Group > ホーム
http://vsug.jp/

vsug.jp にはユーザーが投稿できるフォーラムと呼ばれる掲示板があり、RSS も提供されている。しかし、それらを一気に RSS リーダーに登録する簡単な方法がない。RSS Auto Discovary もないし、OPML もない。

手軽に登録したいので OPML を作った。以下をファイル名 opml.xml などとして文字コード UTF-8 で保存し、OPML 対応の RSS リーダーに読ませればすべてのフォーラムを一気に購読できる。

<?xml version="1.0"?>
<opml version="1.1">
<head>
  <title>Planet .NET Japan</title>
  <dateCreated>Tue, 22 Nov 2005 15:18:02 +0000</dateCreated>
  <dateModified>Tue, 22 Nov 2005 15:18:02 +0000</dateModified>
  <ownerName>Saito Hiroaki</ownerName>
  <ownerEmail><img src="http://sonic64.com/img/mail.png" /></ownerEmail>
</head>

<body>
  <outline text="VSUG - .NET Framework" title="VSUG - .NET Framework" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=51&amp;nossl=x"/>
  <outline text="VSUG - Office 開発・VSTO" title="VSUG - Office 開発・VSTO" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=54&amp;nossl=x"/>
  <outline text="VSUG - VSUGからのお知らせ" title="VSUG - VSUGからのお知らせ" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=70&amp;nossl=x"/>
  <outline text="VSUG - Visual Basic" title="VSUG - Visual Basic" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=44&amp;nossl=x"/>
  <outline text="VSUG - Visual C#" title="VSUG - Visual C#" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=45&amp;nossl=x"/>
  <outline text="VSUG - Visual C++/CLI その他" title="VSUG - Visual C++/CLI その他" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=46&amp;nossl=x"/>
  <outline text="VSUG - Visual Studio 2005" title="VSUG - Visual Studio 2005" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=42&amp;nossl=x"/>
  <outline text="VSUG - Visual Studio 旧環境" title="VSUG - Visual Studio 旧環境" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=43&amp;nossl=x"/>
  <outline text="VSUG - Web アプリケーション" title="VSUG - Web アプリケーション" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=47&amp;nossl=x"/>
  <outline text="VSUG - Web ホスティングアプリケーション" title="VSUG - Web ホスティングアプリケーション" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=55&amp;nossl=x"/>
  <outline text="VSUG - データベース・データアクセス" title="VSUG - データベース・データアクセス" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=49&amp;nossl=x"/>
  <outline text="VSUG - マイグレーション・COM 相互運用" title="VSUG - マイグレーション・COM 相互運用" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=53&amp;nossl=x"/>
  <outline text="VSUG - モバイル・スマートクライアント" title="VSUG - モバイル・スマートクライアント" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=50&amp;nossl=x"/>
  <outline text="VSUG - ライティング・セキュアコード" title="VSUG - ライティング・セキュアコード" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=56&amp;nossl=x"/>
  <outline text="VSUG - リッチクライアント・UI コントロール" title="VSUG - リッチクライアント・UI コントロール" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=48&amp;nossl=x"/>
  <outline text="VSUG - 談話室" title="VSUG - 談話室" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=58&amp;nossl=x"/>
  <outline text="VSUG - 運用管理" title="VSUG - 運用管理" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=57&amp;nossl=x"/>
  <outline text="VSUG - 開発プロセス" title="VSUG - 開発プロセス" type="rss" xmlUrl="http://vsug.jp/Rss/GetRss.aspx?forumid=52&amp;nossl=x"/>
</body>
</opml>

VSUG に投稿しておいた。

Visual Studio User Group > フォーラム > VSUG フォーラム RSS の OPML を作りました
http://vsug.jp/tabid/63/forumid/58/postid/479/view/topic/Def ...

2005-11-11 (Fri)

* Visual Studio 2005 Express Edition の制限

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net]

Visual Studio 2005 Express Edition には制限がある。事実上の無償提供版なので仕方ないけど。

Product Feature Comparisons
http://msdn.microsoft.com/vstudio/products/compare/default.a ...
Extensibility Add external tools to the menu only. Use 3rd party controls.

じゃあ、プラグインを入れたりして、ソリューションエクスプローラからソース管理ツールの Subversion と連携させることはできないってこと? えー。素人は TortoiseSVN でも使ってろって? それでもいい気はするけど、ソリューションエクスプローラとソースコード管理の連携は超便利だからなあ。残念。

prog-blog から。
http://s03.2log.net/home/nsharp/archives/blog385.html
Express Editionには重要な制限事項があります。っていうか、ここにはっきりと書いてあります。

 Extensibility Add external tools to the menu only. Use 3rd party controls.

- Visual Studio 2005 Express Edition 機能比較

Visual Studio 2005 Express Edition には、ほかにもいくつか制限がある。説明が短すぎるので詳細がよくわからないんだけど、気になったものをいくつかメモ。

Data access VB, VC#, VC++, VJ#:local, Visual Web Developer: local and remote

製品によって、使用できるデータベース接続が異なる? 接続文字列変えてもダメなの? そういうレベルじゃない?

Class Designer / Object Test Bench  No

新機能のクラスデザイナも使えないと。これ使いたかったのになあ。

Source Code Control  No

個人的に一番残念なのはこの Source Code Control No だ。他の製品は MSSCCI-compatible (Visual SourceSafe sold separately) なんだけど、Express Edition が No ってことは、ソリューションエクスプローラからソースコード管理できないってこと。前述の Subversion プラグインはおろか、Visual Soource Safe さえ使えないってことだ。

XML Support  XML only

XSLT の開発支援機能も無しと。もっとも、支援機能があったとしても XSLT はあまり近寄りたくはないなあ。

- でも Visual Studio 2005 を使っちゃいそう

GPL の .NET 統合開発環境 SharpDevelop とどっちがいいかな。やっぱりいろいろ制限があっても、仕事でも使ってて慣れてる Visual Studio を選んじゃうんだろうなあ。

2005-11-07 (Mon)

* MCP 70-316 受験レポート 友人編

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [MCP] [.net] [C#]

友達が MCP 70-316 を受験して合格したとのこと。で、受験レポートを寄稿してくれた。載せていい? と聞いたら OK をくれたので、ここに掲載しておく。

友人はメインの開発環境として VS.NET を使っていないとのこと。合格できたのは、繰り返し復習したおかげなんだろうな。iStudy の 70-316 の出来が良くないというのは同意。ちなみに、友人と私はそもそも職場が異なるし、具体的に何を開発しているかはお互い知らない。とても忙しいプロジェクトに参加しているようだ。

■受験時点でのC#経験
以前、C# で開発中のプロジェクトに 5 ヶ月間、ヘルパーとしてプログラミングを
担当する機会があった。
ちなみに本来所属するプロジェクトでは、VS.NET 及び C# は採用していない。
Windows Form の入力画面と、画面で扱うデータを XML Web Service で取得・更新すると
いう、基本的かつ低めのレベルのモジュールを担当していた。

私がこのプロジェクトに参加した時点では、ベースとなるフレームワークが完成済であっ
たため、MCP で問われるような細かい設定等を担当する機会はなかった。
また、言い訳になるがヘルプ要請が急で、業務の時間的制約もあり、深い部分まで理解を
広げることはなかった。

というわけで、私は C# については、初心者に毛を生やした程度のレベルと思われる。
そういうレベルの方の参考になれば幸いである。

■受験勉強
勤務先で、講師を招いての研修会が開催されたので、利用することにした。
研修はカテゴリごとにテキストの解説と iStudy の演習を行うスタイル。
試験合格のみを目的としており、ポイントが明確で得意分野・苦手分野がはっきり掴め
るので、良い研修だと感じた。

ただ、基本的なプロパティや文法などは知っている前提での研修である。
C# での開発経験が全く無いか、非常に浅い方には苦しい研修になる可能性がある。
そういう方は、テキストが事前に配布されるので予め目を通しておくと良いだろう。

毎日の研修後、その日の範囲のテキスト精読と iStudy で復習を行った。
なお、iStudy の品質は劣悪で、設問ミス・回答解説の誤りや不足が多い。
責任問題に発展するのではないかという品質である。

研修では誤っている問題の訂正と丁寧な解説が行われるため、聞き漏らさず、正解選択
肢はもちろん、不正解選択肢についても、本来の使用目的や効果まで把握しておきたい。
ただし、選択肢の中にはそんなプロパティは存在しない、等のでっち上げ選択肢もある。
研修期間終了後は、受験までの1週間、帰宅後に iStudy 模擬試験とテキストの精読を
行った。iStudy 模擬試験では、93 〜 98 % の正答率だった。

■試験会場
R-PROMETRIC 社で申し込み、受験した。

■試験内容
出題は 42 問。
他の方の話を伺うと 50 問以上出題されたという話も聞いた。難易度などを組み合わせて
出題されるのだろうが、詳細は分からない。

私に出題された問題の内訳は、iStudy の内容とほぼ同じか、研修や iStudy で得た知識が
ストレートに問われた問題が約 5 割、その知識を基に思考すれば解ける問題が約 3 割、
残りは回答に必要な知識が不足していると感じる問題であった。

http://sonic64.com/2005-08-28.html の 70-315 のレポートでは、
iStudy をしっかりマスターすれば合格は確実、との内容だが、70-316 はそうではないと感じた。
C# の経験が浅い方は、iStudy や研修テキストの他、実際にコーディングしてみたり、
ヘルプを精読するなど、+αの努力が必要と思われる。

■時間配分
試験時間は 160 分。
1 問目から順に進め、少しでも正解かどうか怪しい問題にはマークを付けて進める。
即答できる問題もあれば、10 分ほど考えた問題もある。勉強不足を痛感した。
全部の問題を一巡した時点で、68 分経過とスローペースであった。

この間、一緒に受験した友人が 60 分ほどで退室。モニターに反射して映る友人の顔には、
晴れやかな余裕の表情が浮かぶ。たぶん合格したのだろう。
少し焦る。
一巡後、マークを付けた問題は 19 問。これらが全て不正解だと、間違いなく不合格だ。
更に焦る。

窓越しに秋雨模様の市街を眺め、気持ちを落ち着けて二巡目へ。
マークを付けていない問題は回答の選択ミスが無いかを確認し、マークを付けた問題は慎
重に再検討した。
二巡目では、回答修正が 2 問、選択ミス発見が 1 問あった。
試験のフォームは、コンポーネントのコントロール領域が広く、不用意なクリックで意図
しない選択肢にチェックが付いてしまうため、必ず見直すようにしたい。
また、マークを付けた問題のうち 7 問は回答に自信を持つことができた。
その結果、マークを付けた問題が 12 問となる。

これらが全て不正解だと、配点によっては不合格の危険性が残る。
だが、うち 6 問は正解候補を二択にまで絞り込めていて数問の正解が見込まれることと、
再度検討しても回答は変わらないと思われることから、終了することにした。
この時点で 103 分経過。

祈る気持ちでテスト終了ボタンをクリックした。
テスト結果を印刷中とのメッセージが 1 分ほど表示された。
緊張感と脱力感、期待と不安が入り交じった、嫌な時間が長く感じられた。
結果は 760 点。薄氷の合格だった。
もっと勉強と経験が必要だ。

合格おめでとう。

2005-10-11 (Tue)

* Reflector for .NET の逆コンパイルでアセンブリのソースを見る

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

Reflector (リフレクター) for .NET を使うと、.NET のアセンブリを逆コンパイルできる。

- Reflector for .NET とは

C# で書かれたコンパイル済みの .NET バイナリや DLL を Reflector でブラウズすると、C# や VB.NET のソースコードとして表示してくれる。.NET のマネージ土コードも逆コンパイルとか逆アセンブルなどと呼ぶのが正しいかわからないけど、その類のもの。いわゆるリバースエンジニアリングのためのツールだ。

Lutz Roeder's Programming.NET C# VB CLR WinFX
http://www.aisto.com/roeder/dotnet/

- Reflector for .NET の使い方

Reflector はインストール方法も使い方も超簡単。 http://www.aisto.com/roeder/dotnet/Download.aspx?File=Reflec ... から zip アーカイブを取得して展開するだけ。現時点の最新バージョンは Version 4.1.85.0 だ。

初回起動時には、どのアセンブリセットをロードするかを選択する。選択すると名前空間ごとにツリーが表示され、その中にある DLL を選んで右クリックし Disassembler を選択すれば、右側に逆アセンブルした結果が表示される。

ブラウズしたいアセンブリの追加も超簡単。左側の名前空間ツリーに DLL をドロップすると、ツリーにその DLL が持つ名前空間が追加されてブラウズできるようになる。

プルダウンメニューを使って、逆アセンブル後の言語を IL、C#、VB.NET、Delphi から選択することもできる。この機能を使えば各言語を相互に変換することもできそうだ。たとえば、VB.NET のソースを C# に変換したりするなど。必要ないのでやらないけど。

- Reflector を使うときはライセンスや著作権に注意

MS のコンサルティングファームの人は、このツールを紹介するときに「Reflector を使って MS の提供している DLL をリバースエンジニアリングすると、ライセンス違反になる可能性がありますよ」と言っていた。でも「便利なツール」とも言っていた。微妙な立場のようだ。

.NET Framework 1.1 の HTTP リクエストクラスである System.Net.HttpWebRequest はドメイン属性が指定されている Cookie を取り扱うことができないというバグを Reflector を使って見つけた話もあることだし、有用なツールであるのは間違いない。ライセンスに注意して使おう。

- Reflector のスペルが覚えられない

2003-07-29 の 「SQL の COALESCE」ほどではないが、Reflector というスペルも覚えにくい。日本人にとって鬼門の R と L の区別の問題があるからだ。Refrector とか Refrecter とか Reflecter などとよく間違えてしまう。正直、このメモにもスペルの間違いがあるんじゃないかと心配になるくらいだ。

2005-10-10 (Mon)

* MCP 70-316 を受験して合格した

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [MCP] [.net] [C#]

MCP 70-316を受験して合格した。以下、2005-08-28 の「MCP 70-315 を受験して合格した」と同じようにメモしておく。

- MCP 70-316

MCP 70-316の正式名称は Developing and Implementing Windows-based Applications with Microsoft Visual C# .NET and Microsoft Visual Studio .NET だ。要するに Visual Studio .NET 環境で C# を使って Windows アプリケーションを開発する開発者向けの試験。前回受験した MCP 70-315 は 70-316 の Web 版みたいな位置づけ。

- 私が受験した MCP 70-316 試験の詳細

MCP 70-316 Developing and Implementing Windows-based Applications with Microsoft Visual C# .NET and Microsoft Visual Studio .NET

試験番号 70-316
試験開催団体 アール・プロメトリック社
受験地 JP241/宇都宮
問題数 43問 (42問だったかも)
試験時間 160分
配点 1000点
合格点 700点
私の得点 1000点

- MCP 70-316 を受験するための学習

MCP 70-316 の受験のために、どのような学習をしたかを列挙。

3日間の研修を受けた。70-315 の時と同じ。
休憩込みで一日8時間弱、3日でカリキュラムが終わるという研修のスタイルも 70-315 と同じ。ポイントを列挙したテキストが用意され、講師がそれを説明。その後すぐさま iSutdy による問題演習と解説というスタイル。ただ、どうも今回は iStudy の点数がふるわない。iStudy 正答率は 50%から 100%の間だったと思う。研修終了時の模擬試験では満点を取れたが、これで本当に大丈夫か不安が残った。

iStudy for MCSD (.NET) CHOICEiStudy for MCSD (.NET) CHOICE

システム・テクノロジー・アイ
発売日: 2003/06/04
Windows

amazon で詳しく見る

iStudy による問題演習。
iStudy については 2005-08-23 の iStudy for MCSD インストールメモを参照。
iStudy の 70-316 の問題は設問や解説の不備、悪問が多い。これらは今後のアップデートで解消されていくだろうが、現時点ではあまりおすすめできる教材ではない。iStudy だけで合格できるかと聞かれたら、私は肯定する返事はしない。

MSDN のドキュメント読み込み。研修で配布されたテキストには、当該テーマの MSDN へのポインタが示されていたので、それを読んでおいた。細かいプロパティや仕様の説明があるので、読んでおくと良い。

あと、70-316 は 70-315 とテーマ的には重複している部分が非常に多いので、すでに 70-315 に合格していればかなり学習時間を節約できると思う。ただ、同じようなテーマなので、学習中はかなり油断と慢心が沸き起こってくる。70-315 でやったから大丈夫などと油断していると大怪我をするかもしれない。

- MCP70-316 で出題された問題の傾向と対策

はっきり言って覚えてない。全体的に 70-315 とテーマが重複している印象が強かった。iStudy で触れられていなかった、細かいプロパティの名前などが出ることもあった。あまり苦手な問題が出題されなかったことと、答えを絞りきれなかった問題が運良く正解になっていたせいもあってか、結果としては満点だった。

- MCP 70-316 受験時の時間配分

試験時間は160分。今回も時間が余った。合格圏内にいる人なら時間は多かれ少なかれ余ると思う。万全を期するために何度も見直しや検討をすれば時間は無くなるだろうが、早ければ30分から90分くらいで終わる。私の所要時間は1時間ちょっとくらいだったかな。一緒に受験した友達は1時間40分くらいだった。

- MCP 70-316 宇都宮試験会場および試験システムについて

70-315 の時と同じく、アール・プロメトリック社の宇都宮試験会場で受験。試験会場である TBC 学院ビルや試験申し込みについては 2005-08-22 の MCP 70-315 宇都宮会場の試験申し込みを参照。

TBC学院ビルへのアクセス。今回も友達に車で送迎してもらった。前回は友達に送迎のお礼として鳩サブレを一枚あげたが、今回は友達の希望の品の蜂蜜をあげた。その友達は前から蜂蜜をほしがっていたのだが、経済的な問題で蜂蜜を買えなかったとのこと。ちなみに、贈った蜂蜜はクローバーの蜂蜜。幼稚園の頃に野生のクローバーの蜜を味わったことがある。蜜の甘い香りが好きだったなあ。クローバーの蜂蜜も同じような味がするのかな?

試験開始時、アンケートに答えるといきなり「成績表を印刷しています」というメッセージが出る。間違った操作をしてしまい、試験が終わってしまったのかと一瞬焦ったが、そういえば前回も同じ文言が出たような記憶がある。メッセージが出てから少しすれば試験が始まるので心配ない。

今回は試験マシンのトラブルはなかった。前回は試験終了時に「成績表を印刷しています」のメッセージのままフリーズするというトラブルに見舞われたが、今回はとくに問題なく、快適そのものだった。おかげで、試験終了時に合否をすぐに確認することもできた。前回は自分の試験マシンでは合否がわからず、係員のいる事務室に行って成績表をもらって初めて合否がわかったので、それまでドキドキ感を味わう羽目になったが、今回は順調だった。

2005-09-13 (Tue)

* C# での変数名などの大文字小文字の使用スタイル

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

今回参加しているプロジェクトで、私が従うべき表記スタイルのメモ。言語は C# がメイン。コーディング標準の一部。HTML Table から引用したので見づらいかも。

ローカル変数名も camel なのか。アンダースコア _ でつなげる方に慣れてたのでちょっと違和感があるが、すぐに慣れるだろう。こういうのはプロジェクト内で統一していることが重要。

大文字小文字の使用スタイル

識別対象 形式 例

名前空間 Pascal System.Drawing
クラス Pascal AppDomain
インターフェイス Pascal IDisposable
列挙型 Pascal ErrorLevel
列挙値 Pascal FatalError
メソッド Pascal ToString
イベント Pascal ValueChange
プロパティ Pascal BackColor
読み取り専用の静的フィールド Pascal RedValue
フィールド変数 _Camel  _redValue
パラメータ(引数) Camel  typeName
局所変数 Camel  redValue
例外クラス Pascal WebException
定数 大文字形式 MAX_VALUE

例外    VS.NET の IDEが自動作成する識別子(メソッド等)については、この規約に従う必要はありません。

識別子における大文字の使用方法として、次の 3 つの形式があります。

Pascal 形式
識別子の最初の文字と、後に続いて連結されている各単語の最初の文字を大文字にします。Pascal 形式は、通常3 文字以上から構成される識別子に対して使用します。次に例を示します。

  BackColor

Camel 形式
識別子の最初の文字は小文字にし、後に続いて連結されている各単語の最初の文字を大文字にします。次に例を示します。

  backColor

大文字形式
識別子のすべての文字を大文字にします。次に例を示します。

  System.IO
  System.Web.UI

大文字形式って、System や Web が大文字になっていないけど、いいのかな? 例が適切じゃないだけか。READ_BUF_SIZE みたいなのが例として適切なのでは?

2005-08-30 (Tue)

* C# の StringCollection と string の配列の変換

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [.net] [C#]

System.Collections.Specialized には StringCollection という string のコレクションを楽に扱えるクラスが用意されている。StringCollection.AddRange() と StringCollection.CopyTo() を使うと、配列と StringCollection の間でデータをやりとりできる。

StringColletion を知る前は、ArrayList を使ったりしてた。キャストの手間が煩わしいとか言ってたような気がする。知らないって怖いなあ。

- String[] から StringCollection に値を渡す

String[] から StringCollection に値を渡すには、StringCollection.AddRange() メソッドを使う。

string[] stringArray = new string[0];
StringCollection sc = new StringCollection();
sc.AddRange(stringArray);

- StringCollection の値を配列に渡す

StringCollection の値を配列に渡すには、StringCollection.CopyTo() メソッドを使う。

StringCollection sc = new StringCollection();
string[] stringArray = new string[sc.Count];
sc.CopyTo(stringArray, 0);

StringCollection.CopyTo() メソッドの存在を知らずに以下のようなコードを書いてしまい、コンパイラに「型 'System.Collections.Specialized.StringCollection' を型 'System.Collections.ArrayList' に変換できません。」というエラーを出力されたことは秘密だ。

// コンパイルエラーになる
string[] stringArray = ((ArrayList)sc).ToArray(typeof(string));

というか、なんで ToArray メソッドが無いんだよー。CopyTo メソッドは開始位置インデックスを指定できるなど高機能であることはわかるけど、低機能でも上位のクラスと同じインターフェイスがあると迷わなくて済むのに。

2005-08-28 (Sun)

* MCP 70-315 を受験して合格した

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [MCP] [.net] [C#]

MCP 70-315 を受験し、無事合格した。いくつか書いておこうと思う。

- 私が受験した MCP 70-315 試験の詳細

MCP 70-315 Developing and Implementing Web Applications with Microsoft Visual C# .NET and Microsoft VisualStudio .NET

試験番号 70-315
受験日 2005年8月27日
試験開催団体 アール・プロメトリック社
受験地 JP241/宇都宮
問題数 43問
試験時間 130分
配点 1000点
合格点 700点
私の得点 829点

- MCP 70-315 を受験するための学習

MCP 70-315 の受験のために、どのような学習をしたかを列挙。

3日間の研修を受けた。
休憩込みで一日8時間弱、3日でカリキュラムが終わるという研修。ポイントを列挙したテキストが用意され、講師がそれを説明。その後すぐさま iSutdy による問題演習と解説というスタイル。この時点での iStudy 正答率は、テーマにもよるが60%から100%で推移していた。全体を通しての正答率の平均は75%くらいかなあ?

iStudy for MCSD (.NET) CHOICEiStudy for MCSD (.NET) CHOICE

システム・テクノロジー・アイ
発売日: 2003/06/04
Windows

amazon で詳しく見る

iStudy による問題演習。
iStudy については 2005-08-23 の iStudy for MCSD インストールメモを参照。
研修の復習という位置づけで、自主的にやった。この時点での正答率、つまり iStudy 2回目の正答率は 80% から 100%くらいだろうか。この時点では iStudy の答えを覚えてしまっていて、問題文を読まなくても正解できる状態になっているはず。でも、それでは勉強にならないので問題文をしっかり読み、少しでも理解が怪しいと思われる問題については iStudy の解説を熟読した。

事前にやったのは、主にこの2つ。あとはテキストを読んだりしていた。合計学習時間は、34時間くらい。内訳は、研修が 8 * 3 で24時間、復習が 2 + 2 + 3 + 3 = 10 時間位だろうか? 復習については良く覚えてないな。月曜日に試験対策の研修が始まり、土曜日に受験というスケジュールだったため、あまり復習している時間がとれなかった。要領のいい人や熟練した ASP.NET の開発者なら、もっと復習の時間が少なくても大丈夫だとは思う。

- 出題された問題の傾向と対策

70-315 は ASP.NET を使った開発をするための知識を問う試験。そのため、ASP.NET で使うクラスや設定ファイル、Visual Studio .NET の使い方、IIS の設定のしかた、SQL の知識などが問われる。普段あまり使わない多言語対応システム、すなわち Internationalization (i18n) や Localization (L10N) の構成方法なども出題される。全体として、とにかくどういう仕組みなのか概要を覚えることが大切。その後、細かい設定ファイルやプロパティを覚えると良いだろう。

本試験では全体的に iStudy で解いた問題と同じ趣旨の問題が出た。iStudy で 90% 以上正解できる力があれば、十分合格を狙えるだろう。さすがにまったく同じ問題というのは無かった気がする。70-315 の iStudy は問題数が 181問しかないので、真面目にこなすとすぐに答えを覚えてしまう。問題文を読まなくても正解できるようになるが、それではダメ。正解の根拠を理解していないと