NameValueCollectionのバグ

同クラスの振る舞いはどう考えても異常なのでちょっと調べてみました。こんな時Javaであれば速攻SDKのソースを見れば解決するのですが.NETのソースコードは入手していないのでちょっと反則ではありますが以前、日記で紹介したReflector for .NETで同クラスのソースコードを追ってみようと思ったのですが..。
ぶっちゃけ日記に書かなければリバースエンジニアリング上等なのですが日記に書く以上、それが例え私用での調査であったとしても.NET Frameworkのライブラリィに関してリバースエンジニアリングを行うことが許可されているかどうかが解らなかったのでやめました。

ならば、と思いいろいろと試していた所やっと原因が判明しました。今回の問題はハンドラのNameValueSectionHandlerクラスではなく内部で使用しているNameValueCollectionクラスにあると思われます。
テストには以下のコードを使用したのですがこの通りに実行すると同様の問題が再現します。

NameValueCollection col = new NameValueCollection();

//コレクションに値を登録(インデクサ)
col["foo"] = "bar1";
col["foo"] = "bar2";
col["foo"] = "bar3";

foreach( string colValue in col.GetValues("foo"))
{
    Console.WriteLine(colValue);
}

このコードの場合、コンソールには"bar3"しか表示されません。ところがコレクションに値を登録するコードをインデクサではなくAddメソッドを使ったコードに変えてみます。

//コレクションに値を登録(メソッド)
col.Add("foo", "bar1");
col.Add("foo", "bar2");
col.Add("foo", "bar3");

今度は実行するとコンソールにはちゃんと

bar1
bar2
bar3

と表示されるのです。

  • 結論 NameValueSectionHandlerはその内部で使用しているNameValueCollectionに値を格納するのにAddメソッドではなくインデクサを使用している(と思われる)。同クラスのインデクサには問題がありはエントリを設定するプロパティでありNameValueCollectionの特徴である同一キーに関連付けられた複数の値を格納するということができない。




こういう場合はやはりソースコードを手軽に覗けるJavaに一理あるなぁ。.

#追記
artonさんのコメントにありますがNameValueCollectionクラスのインデクサの振る舞いはバグではなく仕様通りであることが確認できました。バグと決めつけてしまい申し訳ございませんでした。
以下NameValueCollection.Item プロパティ (String)からの抜粋です。

指定したキーがコレクション内に既に存在する場合は、このプロパティを設定すると、既存の値のリストが指定した値で上書きされます。新しい値を既存の値リストに追加するには、 Add メソッドを使用します。