ILsizeof
命令が必要なものになる可能性があるようです。このsizeof
命令は、C#sizeof
オペレーターによって裏で使用されますが、IL バージョンでは、何らかの理由で制限が少なくなります。
ECMA CLI 仕様(パーティション III、セクション 4.25) には、この命令の説明がありますsizeof
。
型のサイズをバイト単位で返します。typeTok
ジェネリック パラメーター、参照型、または値型にすることができます。
参照型の場合、返されるサイズは、参照値によって参照されるオブジェクトに格納されているデータのサイズではなく、対応する型の参照値のサイズです。
[論理的根拠:値型の定義は、CIL が生成されてから、実行のために読み込まれるまでの間に変更される可能性があります。したがって、型のサイズは、CIL の生成時に常にわかっているわけではありません。このsizeof
命令により、CIL コードは、フレームワーク クラス ライブラリを呼び出す必要なく、実行時にサイズを決定できます。計算は、実行時または CIL からネイティブ コードへのコンパイル時に完全に実行できます。sizeof
この型の配列内の各要素が占有する合計サイズを返します。これには、実装が追加することを選択したパディングが含まれます。具体的には、配列要素はsizeof
バイトごとに離れています。終了理由】
sizeof
少し単純なランタイム コード生成を使用して、命令を取得できるはずです。
Console.WriteLine("Entry is " + TypeHelper.SizeOf(typeof(Entry)) + " bytes.");
// ...
public static class TypeHelper
{
public static int SizeOf<T>(T? obj) where T : struct
{
if (obj == null) throw new ArgumentNullException("obj");
return SizeOf(typeof(T?));
}
public static int SizeOf<T>(T obj)
{
if (obj == null) throw new ArgumentNullException("obj");
return SizeOf(obj.GetType());
}
public static int SizeOf(Type t)
{
if (t == null) throw new ArgumentNullException("t");
return _cache.GetOrAdd(t, t2 =>
{
var dm = new DynamicMethod("$", typeof(int), Type.EmptyTypes);
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, t2);
il.Emit(OpCodes.Ret);
var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>));
return func();
});
}
private static readonly ConcurrentDictionary<Type, int>
_cache = new ConcurrentDictionary<Type, int>();
}