Struct vs Class
C#がJavaと違うところの1つにstruct(値型)をサポートが上げられます。勿論、Javaでもbyteやintなどのプリミティブなものは値型ですが、ユーザ定義の値型はありません。さて、structを使うとパフォーマンスが良いとか、サイズが大きくなったら遅くなるとか言われていますが、実際、どんな感じなんでしょうか? と、いうことで実験してみました。
#region Using directives using System; using System.Collections.Generic; #endregion namespace ConsoleApplication1 { struct StructX { public int x; } class ClassX { public int x; } struct StructXY { public int x; public int y; } class ClassXY { public int x; public int y; } struct StructXYZ { public int x; public int y; public int z; } class ClassXYZ { public int x; public int y; public int z; } class Program { const int SIZE = 1000000; static void Add<T>(int n, ref List<T> list) where T : new() { DateTime t = DateTime.Now; for (int i = 0; i < n; ++i) list.Add(new T() ); string s = String.Format("Add<{0}>", typeof(T).Name); Console.WriteLine(s.PadRight(18) + DateTime.Now.Subtract(t) ); } static void Call<T>(T t) { } static void Call<T>(List<T> list) { DateTime t = DateTime.Now; for (int j = 0; j < 100; ++j) { for (int i = 0; i < list.Count; ++i) { Call<T>(list[i]); } } string s = String.Format("Call<{0}>", typeof(T).Name); Console.WriteLine(s.PadRight(18) + DateTime.Now.Subtract(t) ); } static void CallRef<T>(ref T t) { } static void CallRef<T>(ref T list) { DateTime t = DateTime.Now; for (int j = 0; j < 100; ++j) { for (int i = 0; i < list.Length; ++i) { CallRef <T>(ref list[i]); } } string s = String.Format("CallRef<{0}>", typeof(T).Name); Console.WriteLine(s.PadRight(18) + DateTime.Now.Subtract(t) ); } static void Main(string args) { List<StructX> sx = new List<StructX>(); List<ClassX> cx = new List<ClassX>(); List<StructXY> sxy = new List<StructXY>(); List<ClassXY> cxy = new List<ClassXY>(); List<StructXYZ> sxyz = new List<StructXYZ>(); List<ClassXYZ> cxyz = new List<ClassXYZ>(); Add<StructX>(SIZE, ref sx); Add<ClassX>(SIZE, ref cx); Add<StructXY>(SIZE, ref sxy); Add<ClassXY>(SIZE, ref cxy); Add<StructXYZ>(SIZE, ref sxyz); Add<ClassXYZ>(SIZE, ref cxyz); Call<StructX>(sx); Call<ClassX>(cx); Call<StructXY>(sxy); Call<ClassXY>(cxy); Call<StructXYZ>(sxyz); Call<ClassXYZ>(cxyz); // refで渡す場合 // プロパティはrefで渡せないのでList<T>ではなくArrayを用意 StructXYZ asxyz = new StructXYZ[SIZE]; CallRef<StructXYZ>(ref asxyz); ClassXYZ acxyz = new ClassXYZ[SIZE]; for (int i = 0; i < acxyz.Length; ++i) acxyz[i] = new ClassXYZ(); CallRef<ClassXYZ>(ref acxyz); Console.ReadLine(); } } } /* 結果 Add<StructX> 00:00:00.0468750 Add<ClassX> 00:00:04.2187500 Add<StructXY> 00:00:00.0625000 Add<ClassXY> 00:00:04.3750000 Add<StructXYZ> 00:00:00.0781250 Add<ClassXYZ> 00:00:04.5156250 Call<StructX> 00:00:00.3750000 Call<ClassX> 00:00:00.4687500 Call<StructXY> 00:00:01.9687500 Call<ClassXY> 00:00:00.4687500 Call<StructXYZ> 00:00:02.5781250 Call<ClassXYZ> 00:00:00.4687500 CallRef<StructXYZ>00:00:00.2187500 CallRef<ClassXYZ> 00:00:00.9531250 */
このように、オブジェクトの生成は圧倒的にstructのパフォーマンスが良く、メソッドの引数では、サイズが4バイトまでなら辛うじてstructが勝ちますがそれ以上は、classの方が高速です。概ね言われている通りですね。ちなみにstructを参照渡し(ref)にするとclassよりも高速になりますが、参照渡しのメソッドはプロパティを取ることが出来ず、List