.NET 9 で System.Collections.Generic.OrderedDictionary が追加されたとのことで、見てみましょう。
github.com
■ Dictionary とは何が違うのか
順序が保持される点が違うはずです。OrderedDictionary だけにあるメソッドを見てみると明確です。
var orderdDictTypeMembers = typeof(System.Collections.Generic.OrderedDictionary<string, object>).GetMembers().Select(m=>m.Name).Distinct().Order().ToArray(); var dictTypeMEmbers = typeof(System.Collections.Generic.Dictionary<string, object>).GetMembers().Select(m => m.Name).Distinct().Order().ToArray(); foreach(var name in orderdDictTypeMembers.Except(dictTypeMEmbers).Intersect(orderdDictTypeMembers)) Console.WriteLine(name); // GetAt // IndexOf // Insert // RemoveAt // SetAt
順序を指定して取得/追加/削除/変更がありますね。
OrderedDictionary があると何がうれしいのか
順序も保持する、高速なキーアクセスでの値の取得、両方やらなくちゃならないのがつらいところ......、という場面でうれしいようです。
もし OrderedDictionary がなかったら、順序保持用に List とキーアクセス用に Dictionary、と二重に保持することになるでしょう。そういうコード、何気に書くこと多くあります。
■ 試してみる
Write(Init(new System.Collections.Generic.OrderedDictionary<string, int>())); Write(Init(new System.Collections.Generic.Dictionary<string, int>())); // [c, 0] // [a, 1] // [b, 2] // [c, 0] // [a, 1] // [b, 2] { var ordered = new System.Collections.Generic.OrderedDictionary<string, int>(); Init(ordered); ordered.Insert(1, "d", 3); Write(ordered); } // [c, 0] // [d, 3] // [a, 1] // [b, 2] static IDictionary<string,int> Init(IDictionary<string, int> d) { d.Add("c",0); d.Add("a", 1); d.Add("b", 2); return d; } static void Write(IDictionary<string, int> d) { foreach (var m in d) Console.WriteLine(m); }
Dictionary でも add
した順になっているのでわかりにくいですが、Insert
で追加した場所にちゃんと追加されていますね。
■ 速度に違いはあるのか
Orderされている順でキーアクセスの速度に違いが出るのか、雑に動かしてみます。
var ordered = new System.Collections.Generic.OrderedDictionary<string, int> { { "c", 0 }, { "a", 1 }, { "b", 2 } }; Get(ordered, "a"); // 259760 Get(ordered, "b"); // 90231 Get(ordered, "c"); // 89316 Get(ordered, "a"); // 76363 Get(ordered, "b"); // 39622 Get(ordered, "c"); // 106829 static void Get(IDictionary<string,int> dict, string key) { var sw = Stopwatch.StartNew(); for (long i = 0; i < 100000; ++i) _ = dict[key]; Console.WriteLine(sw.ElapsedTicks); }
速度を目的に使うことは必要なさそうですね。
備えよう
備えよう