型の判別あれこれ

 型の判別で早い方法はないものか調べてみた。

 ソースと実行結果はドクソ長いので後に回して隔離。結果をまとめると、

IsTest 200 192 188
IsAssignableTest 1851 1829 1783
IsInstanceOfTest 764 802 825
IsSubclassOfTest 2947 2899 2857
EqualTest 125 122 120
EqualsTest 335 358 361
SwitchTest 212 228 223
DictionaryTest 245 169 172
DicIntPtrTest 167 167 177
DicArrayTest 136 132 140
CachedDicTest 131 129 143
CachedDicSwitchTest 148 146 157
CachedStringDicTest 189 191 192

 3回繰り返してる。一回目はアセンブリのロードとか入っちゃってるっぽくて正確じゃないっぽい。

 12個のクラスを判別するためにifを12回やってるけど、結局Typeの==が一番速い。継承関係とかないならこれで決まりだろう。Equalsは遅い。

 isも演算子だけあって速い。継承関係も考慮する場合で事前に調べる型が分かってるならこれだろう。

 Dictionaryもそこそこだが12個程度ではif連打の方が速いようだ。Dictionaryを使う場合KeyはTypeでいいみたいだ。

 動的に継承関係も考慮して調べる場合に早い方法が見当たらない。IsInstanceOfTypeがインスタンスを持ってるならそこそこ速いようだ。

 30個にしてみる。調べるのは見込みがありそうなのに絞ってみる。

IsTest 497 500 475
IsInstanceOfTest 1959 2024 2002
EqualTest 207 208 221
DictionaryTest 228 154 164
CachedDicSwitchTest 144 140 151

 30個あるとif連打よりDictionaryがだいぶ速い。あとModule.GetTypeはモジュール内のクラスの数によってスピードが変わっているように見える

ソースと実行結果

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

namespace TestModule
{
	class Parent { }

	class Child1 : Parent { }
	class Child2 : Parent { }
	class Child3 : Parent { }
	class Child4 : Parent { }
	class Child5 : Child1 { }
	class Child6 : Child1 { }
	class Child7 : Child1 { }
	class Child8 : Child1 { }
	class Child9 : Child2 { }
	class Child10 : Child2 { }
	class Child11 : Child2 { }
	class Child12 : Child2 { }
	

	class Program
	{
		const int N = 12;

		Parent[] Generate()
		{
			var rand = new Random();

			var module = typeof(Parent).Module;

	        return Enumerable.Range(0,1000000)
				.Select(
					i => (Parent)Activator.CreateInstance(
						module.GetType("TestModule.Child" + (rand.Next(N) + 1))
					)
				).ToArray();
		}

		int[] IsTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i];
				if (p is Child1) ++array[0];
				if (p is Child2) ++array[1];
				if (p is Child3) ++array[2];
				if (p is Child4) ++array[3];
				if (p is Child5) ++array[4];
				if (p is Child6) ++array[5];
				if (p is Child7) ++array[6];
				if (p is Child8) ++array[7];
				if (p is Child9) ++array[8];
				if (p is Child10) ++array[9];
				if (p is Child11) ++array[10];
				if (p is Child12) ++array[11];
			}

			return array;
		}

		int[] IsAssignableTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i].GetType();
				if (typeof(Child1).IsAssignableFrom(p)) ++array[0];
				if (typeof(Child2).IsAssignableFrom(p)) ++array[1];
				if (typeof(Child3).IsAssignableFrom(p)) ++array[2];
				if (typeof(Child4).IsAssignableFrom(p)) ++array[3];
				if (typeof(Child5).IsAssignableFrom(p)) ++array[4];
				if (typeof(Child6).IsAssignableFrom(p)) ++array[5];
				if (typeof(Child7).IsAssignableFrom(p)) ++array[6];
				if (typeof(Child8).IsAssignableFrom(p)) ++array[7];
				if (typeof(Child9).IsAssignableFrom(p)) ++array[8];
				if (typeof(Child10).IsAssignableFrom(p)) ++array[9];
				if (typeof(Child11).IsAssignableFrom(p)) ++array[10];
				if (typeof(Child12).IsAssignableFrom(p)) ++array[11];
			}

			return array;
		}

		int[] IsInstanceOfTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i];
				if (typeof(Child1).IsInstanceOfType(p)) ++array[0];
				if (typeof(Child2).IsInstanceOfType(p)) ++array[1];
				if (typeof(Child3).IsInstanceOfType(p)) ++array[2];
				if (typeof(Child4).IsInstanceOfType(p)) ++array[3];
				if (typeof(Child5).IsInstanceOfType(p)) ++array[4];
				if (typeof(Child6).IsInstanceOfType(p)) ++array[5];
				if (typeof(Child7).IsInstanceOfType(p)) ++array[6];
				if (typeof(Child8).IsInstanceOfType(p)) ++array[7];
				if (typeof(Child9).IsInstanceOfType(p)) ++array[8];
				if (typeof(Child10).IsInstanceOfType(p)) ++array[9];
				if (typeof(Child11).IsInstanceOfType(p)) ++array[10];
				if (typeof(Child12).IsInstanceOfType(p)) ++array[11];
			}

			return array;
		}

		int[] IsSubClassOfTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i].GetType();
				if (p.IsSubclassOf(typeof(Child1))) ++array[0];
				if (p.IsSubclassOf(typeof(Child2))) ++array[1];
				if (p.IsSubclassOf(typeof(Child3))) ++array[2];
				if (p.IsSubclassOf(typeof(Child4))) ++array[3];
				if (p.IsSubclassOf(typeof(Child5))) ++array[4];
				if (p.IsSubclassOf(typeof(Child6))) ++array[5];
				if (p.IsSubclassOf(typeof(Child7))) ++array[6];
				if (p.IsSubclassOf(typeof(Child8))) ++array[7];
				if (p.IsSubclassOf(typeof(Child9))) ++array[8];
				if (p.IsSubclassOf(typeof(Child10))) ++array[9];
				if (p.IsSubclassOf(typeof(Child11))) ++array[10];
				if (p.IsSubclassOf(typeof(Child12))) ++array[11];
			}

			return array;
		}

		int[] EqualTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i].GetType();
				if (typeof(Child1) == p) ++array[0];
				if (typeof(Child2) == p) ++array[1];
				if (typeof(Child3) == p) ++array[2];
				if (typeof(Child4) == p) ++array[3];
				if (typeof(Child5) == p) ++array[4];
				if (typeof(Child6) == p) ++array[5];
				if (typeof(Child7) == p) ++array[6];
				if (typeof(Child8) == p) ++array[7];
				if (typeof(Child9) == p) ++array[8];
				if (typeof(Child10) == p) ++array[9];
				if (typeof(Child11) == p) ++array[10];
				if (typeof(Child12) == p) ++array[11];
			}

			return array;
		}

		int[] EqualsTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i].GetType();
				if (typeof(Child1).Equals(p)) ++array[0];
				if (typeof(Child2).Equals(p)) ++array[1];
				if (typeof(Child3).Equals(p)) ++array[2];
				if (typeof(Child4).Equals(p)) ++array[3];
				if (typeof(Child5).Equals(p)) ++array[4];
				if (typeof(Child6).Equals(p)) ++array[5];
				if (typeof(Child7).Equals(p)) ++array[6];
				if (typeof(Child8).Equals(p)) ++array[7];
				if (typeof(Child9).Equals(p)) ++array[8];
				if (typeof(Child10).Equals(p)) ++array[9];
				if (typeof(Child11).Equals(p)) ++array[10];
				if (typeof(Child12).Equals(p)) ++array[11];
			}

			return array;
		}

		int[] SwitchTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var n = parents[i].GetType().Name;

				switch (n)
				{
					case "Child1":
						++array[0];
						break;
					case "Child2":
						++array[1];
						break;
					case "Child3":
						++array[2];
						break;
					case "Child4":
						++array[3];
						break;
					case "Child5":
						++array[4];
						break;
					case "Child6":
						++array[5];
						break;
					case "Child7":
						++array[6];
						break;
					case "Child8":
						++array[7];
						break;
					case "Child9":
						++array[8];
						break;
					case "Child10":
						++array[9];
						break;
					case "Child11":
						++array[10];
						break;
					case "Child12":
						++array[11];
						break;
				}
			}
			return array;
		}

		int[] DictionaryTest(Parent[] parents)
		{
			var array = new int[N];

			var d = new Dictionary<RuntimeTypeHandle, Action>();

			d.Add(typeof(Child1).TypeHandle, () => ++array[0]);
			d.Add(typeof(Child2).TypeHandle, () => ++array[1]);
			d.Add(typeof(Child3).TypeHandle, () => ++array[2]);
			d.Add(typeof(Child4).TypeHandle, () => ++array[3]);
			d.Add(typeof(Child5).TypeHandle, () => ++array[4]);
			d.Add(typeof(Child6).TypeHandle, () => ++array[5]);
			d.Add(typeof(Child7).TypeHandle, () => ++array[6]);
			d.Add(typeof(Child8).TypeHandle, () => ++array[7]);
			d.Add(typeof(Child9).TypeHandle, () => ++array[8]);
			d.Add(typeof(Child10).TypeHandle, () => ++array[9]);
			d.Add(typeof(Child11).TypeHandle, () => ++array[10]);
			d.Add(typeof(Child12).TypeHandle, () => ++array[11]);


			for (int i = 0; i < parents.Length; ++i)
			{
				d[Type.GetTypeHandle(parents[i])]();
			}

			return array;
		}

		int[] DictionaryIntPtrTest(Parent[] parents)
		{
			var array = new int[N];

			var d = new Dictionary<IntPtr, Action>();

			d.Add(typeof(Child1).TypeHandle.Value, () => ++array[0]);
			d.Add(typeof(Child2).TypeHandle.Value, () => ++array[1]);
			d.Add(typeof(Child3).TypeHandle.Value, () => ++array[2]);
			d.Add(typeof(Child4).TypeHandle.Value, () => ++array[3]);
			d.Add(typeof(Child5).TypeHandle.Value, () => ++array[4]);
			d.Add(typeof(Child6).TypeHandle.Value, () => ++array[5]);
			d.Add(typeof(Child7).TypeHandle.Value, () => ++array[6]);
			d.Add(typeof(Child8).TypeHandle.Value, () => ++array[7]);
			d.Add(typeof(Child9).TypeHandle.Value, () => ++array[8]);
			d.Add(typeof(Child10).TypeHandle.Value, () => ++array[9]);
			d.Add(typeof(Child11).TypeHandle.Value, () => ++array[10]);
			d.Add(typeof(Child12).TypeHandle.Value, () => ++array[11]);

			for (int i = 0; i < parents.Length; ++i)
			{
				d[Type.GetTypeHandle(parents[i]).Value]();
			}

			return array;
		}

		int[] DictionaryArrayTest(Parent[] parents)
		{
			var array = new int[N];
			
			var d = new Dictionary<RuntimeTypeHandle, int>();

			d.Add(typeof(Child1).TypeHandle, 0);
			d.Add(typeof(Child2).TypeHandle, 1);
			d.Add(typeof(Child3).TypeHandle, 2);
			d.Add(typeof(Child4).TypeHandle, 3);
			d.Add(typeof(Child5).TypeHandle, 4);
			d.Add(typeof(Child6).TypeHandle, 5);
			d.Add(typeof(Child7).TypeHandle, 6);
			d.Add(typeof(Child8).TypeHandle, 7);
			d.Add(typeof(Child9).TypeHandle, 8);
			d.Add(typeof(Child10).TypeHandle, 9);
			d.Add(typeof(Child11).TypeHandle, 10);
			d.Add(typeof(Child12).TypeHandle, 11);

			for (int i = 0; i < parents.Length; ++i)
			{
				++array[d[Type.GetTypeHandle(parents[i])]];
			}

			return array;
		}

		int[] CachedDictionaryTest(Parent[] parents, Dictionary<RuntimeTypeHandle, int> d)
		{
			var array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				++array[d[Type.GetTypeHandle(parents[i])]];
			}

			return array;
		}

		int[] CachedDictionarySwitchTest(Parent[] parents, Dictionary<RuntimeTypeHandle, int> d)
		{
			var array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var a = d[Type.GetTypeHandle(parents[i])];

				switch (a)
				{
					case 0:
						++array[0];
						break;
					case 1:
						++array[1];
						break;
					case 2:
						++array[2];
						break;
					case 3:
						++array[3];
						break;
					case 4:
						++array[4];
						break;
					case 5:
						++array[5];
						break;
					case 6:
						++array[6];
						break;
					case 7:
						++array[7];
						break;
					case 8:
						++array[8];
						break;
					case 9:
						++array[9];
						break;
					case 10:
						++array[10];
						break;
					case 11:
						++array[11];
						break;
				}
			}

			return array;
		}


		int[] CachedStringDictionaryTest(Parent[] parents, Dictionary<string, int> d)
		{
			var array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				++array[d[parents[i].GetType().Name]];
			}

			return array;
		}

		void Do(Parent[] parents)
		{
			var sw = new Stopwatch();
			sw.Reset();
			sw.Start();
			var isTest = IsTest(parents);
			sw.Stop();
			Console.WriteLine("IsTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var isAssignableTest = IsAssignableTest(parents);
			sw.Stop();
			Console.WriteLine("IsAssignableTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var isInstanceOfTest = IsInstanceOfTest(parents);
			sw.Stop();
			Console.WriteLine("IsInstanceOfTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var isSubclassOfTest = IsSubClassOfTest(parents);
			sw.Stop();
			Console.WriteLine("IsSubclassOfTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var equalTest = EqualTest(parents);
			sw.Stop();
			Console.WriteLine("EqualTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var equalsTest = EqualsTest(parents);
			sw.Stop();
			Console.WriteLine("EqualsTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var switchTest = SwitchTest(parents);
			sw.Stop();
			Console.WriteLine("SwitchTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var dicTest = DictionaryTest(parents);
			sw.Stop();
			Console.WriteLine("DictionaryTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var dicIntPtrTest = DictionaryIntPtrTest(parents);
			sw.Stop();
			Console.WriteLine("DicIntPtrTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var dicArrayTest = DictionaryArrayTest(parents);
			sw.Stop();
			Console.WriteLine("DicArrayTest " + Tick(sw));


			var d = new Dictionary<RuntimeTypeHandle, int>();

			d.Add(typeof(Child1).TypeHandle, 0);
			d.Add(typeof(Child2).TypeHandle, 1);
			d.Add(typeof(Child3).TypeHandle, 2);
			d.Add(typeof(Child4).TypeHandle, 3);
			d.Add(typeof(Child5).TypeHandle, 4);
			d.Add(typeof(Child6).TypeHandle, 5);
			d.Add(typeof(Child7).TypeHandle, 6);
			d.Add(typeof(Child8).TypeHandle, 7);
			d.Add(typeof(Child9).TypeHandle, 8);
			d.Add(typeof(Child10).TypeHandle, 9);
			d.Add(typeof(Child11).TypeHandle, 10);
			d.Add(typeof(Child12).TypeHandle, 11);

			sw.Reset();
			sw.Start();
			var cachedTest = CachedDictionaryTest(parents,d);
			sw.Stop();
			Console.WriteLine("CachedDicTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var cachedDicSwitchTest = CachedDictionarySwitchTest(parents, d);
			sw.Stop();
			Console.WriteLine("CachedDicSwitchTest " + Tick(sw));

			var d2 = new Dictionary<string, int>();

			d2.Add(typeof(Child1).Name, 0);
			d2.Add(typeof(Child2).Name, 1);
			d2.Add(typeof(Child3).Name, 2);
			d2.Add(typeof(Child4).Name, 3);
			d2.Add(typeof(Child5).Name, 4);
			d2.Add(typeof(Child6).Name, 5);
			d2.Add(typeof(Child7).Name, 6);
			d2.Add(typeof(Child8).Name, 7);
			d2.Add(typeof(Child9).Name, 8);
			d2.Add(typeof(Child10).Name, 9);
			d2.Add(typeof(Child11).Name, 10);
			d2.Add(typeof(Child12).Name, 11);

			sw.Reset();
			sw.Start();
			var cachedStringDicTest = CachedStringDictionaryTest(parents, d2);
			sw.Stop();
			Console.WriteLine("CachedStringDicTest " + Tick(sw));

			for (int i = 0; i < isTest.Length; ++i)
			{
				Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}",
					isTest[i], isAssignableTest[i], isInstanceOfTest[i], isSubclassOfTest[i],switchTest[i],
					dicTest[i], dicIntPtrTest[i], dicArrayTest[i], cachedTest[i], cachedStringDicTest[i], 
					equalTest[i], equalsTest[i], cachedDicSwitchTest[i]);
			}
		}

		long Tick(Stopwatch sw)
		{
			return sw.ElapsedMilliseconds;
		}

		static void Main()
		{
			var p = new Program();
			Stopwatch sw = new Stopwatch();

			sw.Start();
			var parents = p.Generate();
			sw.Stop();
			Console.WriteLine("Generate " + p.Tick(sw));


			p.Do(parents);
			p.Do(parents);
			p.Do(parents);

			System.Windows.Forms.Application.Run(new Form1());
		}


	}
}

Generate 13690
IsTest 200
IsAssignableTest 1851
IsInstanceOfTest 764
IsSubclassOfTest 2947
EqualTest 125
EqualsTest 335
SwitchTest 212
DictionaryTest 245
DicIntPtrTest 167
DicArrayTest 136
CachedDicTest 131
CachedDicSwitchTest 148
CachedStringDicTest 189
416466 416466 416466 332998 83468 83468 83468 83468 83468 83468 83468 83468
416291 416291 416291 332692 83599 83599 83599 83599 83599 83599 83599 83599
83665 83665 83665 0 83665 83665 83665 83665 83665 83665 83665 83665
83578 83578 83578 0 83578 83578 83578 83578 83578 83578 83578 83578
83253 83253 83253 0 83253 83253 83253 83253 83253 83253 83253 83253
83179 83179 83179 0 83179 83179 83179 83179 83179 83179 83179 83179
83200 83200 83200 0 83200 83200 83200 83200 83200 83200 83200 83200
83366 83366 83366 0 83366 83366 83366 83366 83366 83366 83366 83366
83486 83486 83486 0 83486 83486 83486 83486 83486 83486 83486 83486
82733 82733 82733 0 82733 82733 82733 82733 82733 82733 82733 82733
83211 83211 83211 0 83211 83211 83211 83211 83211 83211 83211 83211
83262 83262 83262 0 83262 83262 83262 83262 83262 83262 83262 83262
IsTest 192
IsAssignableTest 1829
IsInstanceOfTest 802
IsSubclassOfTest 2899
EqualTest 122
EqualsTest 358
SwitchTest 228
DictionaryTest 169
DicIntPtrTest 167
DicArrayTest 132
CachedDicTest 129
CachedDicSwitchTest 146
CachedStringDicTest 191
416466 416466 416466 332998 83468 83468 83468 83468 83468 83468 83468 83468
416291 416291 416291 332692 83599 83599 83599 83599 83599 83599 83599 83599
83665 83665 83665 0 83665 83665 83665 83665 83665 83665 83665 83665
83578 83578 83578 0 83578 83578 83578 83578 83578 83578 83578 83578
83253 83253 83253 0 83253 83253 83253 83253 83253 83253 83253 83253
83179 83179 83179 0 83179 83179 83179 83179 83179 83179 83179 83179
83200 83200 83200 0 83200 83200 83200 83200 83200 83200 83200 83200
83366 83366 83366 0 83366 83366 83366 83366 83366 83366 83366 83366
83486 83486 83486 0 83486 83486 83486 83486 83486 83486 83486 83486
82733 82733 82733 0 82733 82733 82733 82733 82733 82733 82733 82733
83211 83211 83211 0 83211 83211 83211 83211 83211 83211 83211 83211
83262 83262 83262 0 83262 83262 83262 83262 83262 83262 83262 83262
IsTest 188
スレッド 0x1c34c はコード 0 (0x0) で終了しました。
IsAssignableTest 1783
IsInstanceOfTest 825
IsSubclassOfTest 2857
EqualTest 120
EqualsTest 361
SwitchTest 223
DictionaryTest 172
DicIntPtrTest 177
DicArrayTest 140
CachedDicTest 143
CachedDicSwitchTest 157
CachedStringDicTest 192
416466 416466 416466 332998 83468 83468 83468 83468 83468 83468 83468 83468
416291 416291 416291 332692 83599 83599 83599 83599 83599 83599 83599 83599
83665 83665 83665 0 83665 83665 83665 83665 83665 83665 83665 83665
83578 83578 83578 0 83578 83578 83578 83578 83578 83578 83578 83578
83253 83253 83253 0 83253 83253 83253 83253 83253 83253 83253 83253
83179 83179 83179 0 83179 83179 83179 83179 83179 83179 83179 83179
83200 83200 83200 0 83200 83200 83200 83200 83200 83200 83200 83200
83366 83366 83366 0 83366 83366 83366 83366 83366 83366 83366 83366
83486 83486 83486 0 83486 83486 83486 83486 83486 83486 83486 83486
82733 82733 82733 0 82733 82733 82733 82733 82733 82733 82733 82733
83211 83211 83211 0 83211 83211 83211 83211 83211 83211 83211 83211
83262 83262 83262 0 83262 83262 83262 83262 83262 83262 83262 83262

30個版

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

namespace TestModule2
{
	class Parent { }

	class Child1 : Parent { }
	class Child2 : Parent { }
	class Child3 : Parent { }
	class Child4 : Parent { }
	class Child5 : Child1 { }
	class Child6 : Child1 { }
	class Child7 : Child1 { }
	class Child8 : Child1 { }
	class Child9 : Child2 { }
	class Child10 : Child2 { }
	class Child11 : Child2 { }
	class Child12 : Child2 { }
	class Child13 : Child3 { }
	class Child14 : Child3 { }
	class Child15 : Child3 { }
	class Child16 : Child3 { }
	class Child17 : Child4 { }
	class Child18 : Child4 { }
	class Child19 : Child4 { }
	class Child20 : Child4 { }
	class Child21 : Child5 { }
	class Child22 : Child5 { }
	class Child23 : Child5 { }
	class Child24 : Child5 { }
	class Child25 : Child6 { }
	class Child26 : Child6 { }
	class Child27 : Child6 { }
	class Child28 : Child6 { }
	class Child29 : Child7 { }
	class Child30 : Child7 { }
	

	class Program2
	{
		const int N = 30;

		Parent[] Generate()
		{
			var rand = new Random();

			var module = typeof(Parent).Module;

	        return Enumerable.Range(0,1000000)
				.Select(
					i => (Parent)Activator.CreateInstance(
						module.GetType("TestModule2.Child" + (rand.Next(N) + 1))
					)
				).ToArray();
		}

		int[] IsTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i];
				if (p is Child1) ++array[0];
				if (p is Child2) ++array[1];
				if (p is Child3) ++array[2];
				if (p is Child4) ++array[3];
				if (p is Child5) ++array[4];
				if (p is Child6) ++array[5];
				if (p is Child7) ++array[6];
				if (p is Child8) ++array[7];
				if (p is Child9) ++array[8];
				if (p is Child10) ++array[9];
				if (p is Child11) ++array[10];
				if (p is Child12) ++array[11];
				if (p is Child13) ++array[12];
				if (p is Child14) ++array[13];
				if (p is Child15) ++array[14];
				if (p is Child16) ++array[15];
				if (p is Child17) ++array[16];
				if (p is Child18) ++array[17];
				if (p is Child19) ++array[18];
				if (p is Child10) ++array[19];
				if (p is Child21) ++array[20];
				if (p is Child22) ++array[21];
				if (p is Child23) ++array[22];
				if (p is Child24) ++array[23];
				if (p is Child25) ++array[24];
				if (p is Child26) ++array[25];
				if (p is Child27) ++array[26];
				if (p is Child28) ++array[27];
				if (p is Child29) ++array[28];
				if (p is Child30) ++array[29];
			}

			return array;
		}

		int[] IsInstanceOfTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i];
				if (typeof(Child1).IsInstanceOfType(p)) ++array[0];
				if (typeof(Child2).IsInstanceOfType(p)) ++array[1];
				if (typeof(Child3).IsInstanceOfType(p)) ++array[2];
				if (typeof(Child4).IsInstanceOfType(p)) ++array[3];
				if (typeof(Child5).IsInstanceOfType(p)) ++array[4];
				if (typeof(Child6).IsInstanceOfType(p)) ++array[5];
				if (typeof(Child7).IsInstanceOfType(p)) ++array[6];
				if (typeof(Child8).IsInstanceOfType(p)) ++array[7];
				if (typeof(Child9).IsInstanceOfType(p)) ++array[8];
				if (typeof(Child10).IsInstanceOfType(p)) ++array[9];
				if (typeof(Child11).IsInstanceOfType(p)) ++array[10];
				if (typeof(Child12).IsInstanceOfType(p)) ++array[11];
				if (typeof(Child13).IsInstanceOfType(p)) ++array[12];
				if (typeof(Child14).IsInstanceOfType(p)) ++array[13];
				if (typeof(Child15).IsInstanceOfType(p)) ++array[14];
				if (typeof(Child16).IsInstanceOfType(p)) ++array[15];
				if (typeof(Child17).IsInstanceOfType(p)) ++array[16];
				if (typeof(Child18).IsInstanceOfType(p)) ++array[17];
				if (typeof(Child19).IsInstanceOfType(p)) ++array[18];
				if (typeof(Child20).IsInstanceOfType(p)) ++array[19];
				if (typeof(Child21).IsInstanceOfType(p)) ++array[20];
				if (typeof(Child22).IsInstanceOfType(p)) ++array[21];
				if (typeof(Child23).IsInstanceOfType(p)) ++array[22];
				if (typeof(Child24).IsInstanceOfType(p)) ++array[23];
				if (typeof(Child25).IsInstanceOfType(p)) ++array[24];
				if (typeof(Child26).IsInstanceOfType(p)) ++array[25];
				if (typeof(Child27).IsInstanceOfType(p)) ++array[26];
				if (typeof(Child28).IsInstanceOfType(p)) ++array[27];
				if (typeof(Child29).IsInstanceOfType(p)) ++array[28];
				if (typeof(Child30).IsInstanceOfType(p)) ++array[29];
				
			}

			return array;
		}

		int[] EqualTest(Parent[] parents)
		{
			int[] array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var p = parents[i].GetType();
				if (typeof(Child1) == p) ++array[0];
				if (typeof(Child2) == p) ++array[1];
				if (typeof(Child3) == p) ++array[2];
				if (typeof(Child4) == p) ++array[3];
				if (typeof(Child5) == p) ++array[4];
				if (typeof(Child6) == p) ++array[5];
				if (typeof(Child7) == p) ++array[6];
				if (typeof(Child8) == p) ++array[7];
				if (typeof(Child9) == p) ++array[8];
				if (typeof(Child10) == p) ++array[9];
				if (typeof(Child11) == p) ++array[10];
				if (typeof(Child12) == p) ++array[11];
				if (typeof(Child13) == p) ++array[12];
				if (typeof(Child14) == p) ++array[13];
				if (typeof(Child15) == p) ++array[14];
				if (typeof(Child16) == p) ++array[15];
				if (typeof(Child17) == p) ++array[16];
				if (typeof(Child18) == p) ++array[17];
				if (typeof(Child19) == p) ++array[18];
				if (typeof(Child20) == p) ++array[19];
				if (typeof(Child21) == p) ++array[20];
				if (typeof(Child22) == p) ++array[21];
				if (typeof(Child23) == p) ++array[22];
				if (typeof(Child24) == p) ++array[23];
				if (typeof(Child25) == p) ++array[24];
				if (typeof(Child26) == p) ++array[25];
				if (typeof(Child27) == p) ++array[26];
				if (typeof(Child28) == p) ++array[27];
				if (typeof(Child29) == p) ++array[28];
				if (typeof(Child30) == p) ++array[29];
			}

			return array;
		}	

		int[] DictionaryTest(Parent[] parents)
		{
			var array = new int[N];

			var d = new Dictionary<RuntimeTypeHandle, Action>();

			d.Add(typeof(Child1).TypeHandle, () => ++array[0]);
			d.Add(typeof(Child2).TypeHandle, () => ++array[1]);
			d.Add(typeof(Child3).TypeHandle, () => ++array[2]);
			d.Add(typeof(Child4).TypeHandle, () => ++array[3]);
			d.Add(typeof(Child5).TypeHandle, () => ++array[4]);
			d.Add(typeof(Child6).TypeHandle, () => ++array[5]);
			d.Add(typeof(Child7).TypeHandle, () => ++array[6]);
			d.Add(typeof(Child8).TypeHandle, () => ++array[7]);
			d.Add(typeof(Child9).TypeHandle, () => ++array[8]);
			d.Add(typeof(Child10).TypeHandle, () => ++array[9]);
			d.Add(typeof(Child11).TypeHandle, () => ++array[10]);
			d.Add(typeof(Child12).TypeHandle, () => ++array[11]);
			d.Add(typeof(Child13).TypeHandle, () => ++array[12]);
			d.Add(typeof(Child14).TypeHandle, () => ++array[13]);
			d.Add(typeof(Child15).TypeHandle, () => ++array[14]);
			d.Add(typeof(Child16).TypeHandle, () => ++array[15]);
			d.Add(typeof(Child17).TypeHandle, () => ++array[16]);
			d.Add(typeof(Child18).TypeHandle, () => ++array[17]);
			d.Add(typeof(Child19).TypeHandle, () => ++array[18]);
			d.Add(typeof(Child20).TypeHandle, () => ++array[19]);
			d.Add(typeof(Child21).TypeHandle, () => ++array[20]);
			d.Add(typeof(Child22).TypeHandle, () => ++array[21]);
			d.Add(typeof(Child23).TypeHandle, () => ++array[22]);
			d.Add(typeof(Child24).TypeHandle, () => ++array[23]);
			d.Add(typeof(Child25).TypeHandle, () => ++array[24]);
			d.Add(typeof(Child26).TypeHandle, () => ++array[25]);
			d.Add(typeof(Child27).TypeHandle, () => ++array[26]);
			d.Add(typeof(Child28).TypeHandle, () => ++array[27]);
			d.Add(typeof(Child29).TypeHandle, () => ++array[28]);
			d.Add(typeof(Child30).TypeHandle, () => ++array[29]);


			for (int i = 0; i < parents.Length; ++i)
			{
				d[Type.GetTypeHandle(parents[i])]();
			}

			return array;
		}

		int[] CachedDictionarySwitchTest(Parent[] parents, Dictionary<RuntimeTypeHandle, int> d)
		{
			var array = new int[N];

			for (int i = 0; i < parents.Length; ++i)
			{
				var a = d[Type.GetTypeHandle(parents[i])];

				switch (a)
				{
					case 0:
						++array[0];
						break;
					case 1:
						++array[1];
						break;
					case 2:
						++array[2];
						break;
					case 3:
						++array[3];
						break;
					case 4:
						++array[4];
						break;
					case 5:
						++array[5];
						break;
					case 6:
						++array[6];
						break;
					case 7:
						++array[7];
						break;
					case 8:
						++array[8];
						break;
					case 9:
						++array[9];
						break;
					case 10:
						++array[10];
						break;
					case 11:
						++array[11];
						break;
					case 12:
						++array[12];
						break;
					case 13:
						++array[13];
						break;
					case 14:
						++array[14];
						break;
					case 15:
						++array[15];
						break;
					case 16:
						++array[16];
						break;
					case 17:
						++array[17];
						break;
					case 18:
						++array[18];
						break;
					case 19:
						++array[19];
						break;
					case 20:
						++array[20];
						break;
					case 21:
						++array[21];
						break;
					case 22:
						++array[22];
						break;
					case 23:
						++array[23];
						break;
					case 24:
						++array[24];
						break;
					case 25:
						++array[25];
						break;
					case 26:
						++array[26];
						break;
					case 27:
						++array[27];
						break;
					case 28:
						++array[28];
						break;
					case 29:
						++array[29];
						break;
					case 30:
						++array[30];
						break;
				}
			}

			return array;
		}

		void Do(Parent[] parents)
		{
			var sw = new Stopwatch();
			sw.Reset();
			sw.Start();
			var isTest = IsTest(parents);
			sw.Stop();
			Console.WriteLine("IsTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var isInstanceOfTest = IsInstanceOfTest(parents);
			sw.Stop();
			Console.WriteLine("IsInstanceOfTest " + Tick(sw));

			sw.Reset();
			sw.Start();
			var equalTest = EqualTest(parents);
			sw.Stop();
			Console.WriteLine("EqualTest " + Tick(sw));


			sw.Reset();
			sw.Start();
			var dicTest = DictionaryTest(parents);
			sw.Stop();
			Console.WriteLine("DictionaryTest " + Tick(sw));

			var d = new Dictionary<RuntimeTypeHandle, int>();

			d.Add(typeof(Child1).TypeHandle, 0);
			d.Add(typeof(Child2).TypeHandle, 1);
			d.Add(typeof(Child3).TypeHandle, 2);
			d.Add(typeof(Child4).TypeHandle, 3);
			d.Add(typeof(Child5).TypeHandle, 4);
			d.Add(typeof(Child6).TypeHandle, 5);
			d.Add(typeof(Child7).TypeHandle, 6);
			d.Add(typeof(Child8).TypeHandle, 7);
			d.Add(typeof(Child9).TypeHandle, 8);
			d.Add(typeof(Child10).TypeHandle, 9);
			d.Add(typeof(Child11).TypeHandle, 10);
			d.Add(typeof(Child12).TypeHandle, 11);
			d.Add(typeof(Child13).TypeHandle, 12);
			d.Add(typeof(Child14).TypeHandle, 13);
			d.Add(typeof(Child15).TypeHandle, 14);
			d.Add(typeof(Child16).TypeHandle, 15);
			d.Add(typeof(Child17).TypeHandle, 16);
			d.Add(typeof(Child18).TypeHandle, 17);
			d.Add(typeof(Child19).TypeHandle, 18);
			d.Add(typeof(Child20).TypeHandle, 19);
			d.Add(typeof(Child21).TypeHandle, 20);
			d.Add(typeof(Child22).TypeHandle, 21);
			d.Add(typeof(Child23).TypeHandle, 22);
			d.Add(typeof(Child24).TypeHandle, 23);
			d.Add(typeof(Child25).TypeHandle, 24);
			d.Add(typeof(Child26).TypeHandle, 25);
			d.Add(typeof(Child27).TypeHandle, 26);
			d.Add(typeof(Child28).TypeHandle, 27);
			d.Add(typeof(Child29).TypeHandle, 28);
			d.Add(typeof(Child30).TypeHandle, 29);

			sw.Reset();
			sw.Start();
			var cachedDicSwitchTest = CachedDictionarySwitchTest(parents, d);
			sw.Stop();
			Console.WriteLine("CachedDicSwitchTest " + Tick(sw));

			
			for (int i = 0; i < isTest.Length; ++i)
			{
				Console.WriteLine("{0} {1} {2} {3} {4}",
				    isTest[i],isInstanceOfTest[i], 
				    dicTest[i], 
				    equalTest[i], cachedDicSwitchTest[i]);
			}
		}

		long Tick(Stopwatch sw)
		{
			return sw.ElapsedMilliseconds;
		}

		static void Main()
		{
			var p = new Program2();
			Stopwatch sw = new Stopwatch();

			sw.Start();
			var parents = p.Generate();
			sw.Stop();
			Console.WriteLine("Generate " + p.Tick(sw));


			p.Do(parents);
			p.Do(parents);
			p.Do(parents);

			System.Windows.Forms.Application.Run(new System.Windows.Forms.Form());
		}


	}
}
Generate 23381
IsTest 497
IsInstanceOfTest 1959
EqualTest 207
DictionaryTest 228
CachedDicSwitchTest 144
499426 499426 33205 33205 33205
166155 166155 33245 33245 33245
167171 167171 33346 33346 33346
167248 167248 33541 33541 33541
166226 166226 33158 33158 33158
166204 166204 33149 33149 33149
100003 100003 33316 33316 33316
33788 33788 33788 33788 33788
32968 32968 32968 32968 32968
33299 33299 33299 33299 33299
33195 33195 33195 33195 33195
33448 33448 33448 33448 33448
33585 33585 33585 33585 33585
33434 33434 33434 33434 33434
33373 33373 33373 33373 33373
33433 33433 33433 33433 33433
33618 33618 33618 33618 33618
33424 33424 33424 33424 33424
33325 33325 33325 33325 33325
33299 33340 33340 33340 33340
33443 33443 33443 33443 33443
33167 33167 33167 33167 33167
33257 33257 33257 33257 33257
33201 33201 33201 33201 33201
33151 33151 33151 33151 33151
33426 33426 33426 33426 33426
33483 33483 33483 33483 33483
32995 32995 32995 32995 32995
33543 33543 33543 33543 33543
33144 33144 33144 33144 33144
IsTest 500
IsInstanceOfTest 2024
EqualTest 208
DictionaryTest 154
CachedDicSwitchTest 140
499426 499426 33205 33205 33205
166155 166155 33245 33245 33245
167171 167171 33346 33346 33346
167248 167248 33541 33541 33541
166226 166226 33158 33158 33158
166204 166204 33149 33149 33149
100003 100003 33316 33316 33316
33788 33788 33788 33788 33788
32968 32968 32968 32968 32968
33299 33299 33299 33299 33299
33195 33195 33195 33195 33195
33448 33448 33448 33448 33448
33585 33585 33585 33585 33585
33434 33434 33434 33434 33434
33373 33373 33373 33373 33373
33433 33433 33433 33433 33433
33618 33618 33618 33618 33618
33424 33424 33424 33424 33424
33325 33325 33325 33325 33325
33299 33340 33340 33340 33340
33443 33443 33443 33443 33443
33167 33167 33167 33167 33167
33257 33257 33257 33257 33257
33201 33201 33201 33201 33201
33151 33151 33151 33151 33151
33426 33426 33426 33426 33426
33483 33483 33483 33483 33483
32995 32995 32995 32995 32995
33543 33543 33543 33543 33543
33144 33144 33144 33144 33144
IsTest 475
IsInstanceOfTest 2002
EqualTest 221
DictionaryTest 164
CachedDicSwitchTest 151
499426 499426 33205 33205 33205
166155 166155 33245 33245 33245
167171 167171 33346 33346 33346
167248 167248 33541 33541 33541
166226 166226 33158 33158 33158
166204 166204 33149 33149 33149
100003 100003 33316 33316 33316
33788 33788 33788 33788 33788
32968 32968 32968 32968 32968
33299 33299 33299 33299 33299
33195 33195 33195 33195 33195
33448 33448 33448 33448 33448
33585 33585 33585 33585 33585
33434 33434 33434 33434 33434
33373 33373 33373 33373 33373
33433 33433 33433 33433 33433
33618 33618 33618 33618 33618
33424 33424 33424 33424 33424
33325 33325 33325 33325 33325
33299 33340 33340 33340 33340
33443 33443 33443 33443 33443
33167 33167 33167 33167 33167
33257 33257 33257 33257 33257
33201 33201 33201 33201 33201
33151 33151 33151 33151 33151
33426 33426 33426 33426 33426
33483 33483 33483 33483 33483
32995 32995 32995 32995 32995
33543 33543 33543 33543 33543
33144 33144 33144 33144 33144
スレッド 0x1d0ec はコード 0 (0x0) で終了しました。

|