[WPF]ListBox.SelectedIndexが勝手に変わると思ったら

ListBoxを配置して、適当に数値だけをメンバに持つオブジェクトをリストにして
ItemsSourceに格納します。
検証環境のビルドターゲットは.NET 4.0。

//リスト項目クラス
public sealed class NumItem
{
    readonly int num;

    public NumItem(int num)
    {
        this.num = num;
    }

    public override string ToString()
    {
        return num.ToString();
    }

    public override bool Equals(object obj)
    {
        var other = obj as NumItem;
        if (other == null) return false;

        //数値が同じなら等価とみなす
        return this.num == other.num;
    }

    public override int GetHashCode()
    {
        return this.num.GetHashCode();
    }
}
//1,2,3の3行をリスト化
listbox.ItemsSource = new[] { 1, 2, 3 }.Select(n => new NumItem(n)).ToArray();

この状態でSelectedItemプロパティに、存在しない項目(4)を設定する。
すると、選択できるわけがないので、
そのあとにSelectedItemプロパティを参照するとNullが返るし、
SelectedIndexは-1を返す。

listbox.SelectedItem = new NumItem(4);
Console.WriteLine(listbox.SelectedItem == null);  // true
Console.WriteLine(listbox.SelectedIndex);  // -1

SelectedItemを設定する代わりに、SelectedIndex = 3 などとやっても同じ結果。
ここまでは想定どおりである。

ところが、そのあとに項目4を含むリストをItemSourceに再設定してやると、
なんとさっきの情報を覚えていて、
おせっかいにも勝手に選択してくれやがるじゃないですか。

listbox.SelectedItem = new NumItem(4);
listbox.ItemsSource = new[] { 1, 2, 3, 4 }.Select(n => new NumItem(n)).ToArray();
Console.WriteLine(listbox.SelectedItem);   // 4
Console.WriteLine(listbox.SelectedIndex);  // 3

SelectedIndex = 3とやった場合もやはり同じ結果になる。
おそらく直前に設定された値を内部的に覚えてるんだろうな。

もちろんリストに存在しない項目を選択するなんていう
気持ち悪いことをやらなきゃいい話なんだけど、
というか自分ではこんなコード書かないだろうけども、
他の人の作ったアプリが変な挙動していて
調査してたらここに原因があってだいぶはまりましたとさ。