5

を使用して、さまざまなタイプのさまざまなオブジェクトのバイトを取得しようとしていますBitConverter.GetBytes。これを行うには、使用するすべてのタイプ (short、long、ulong など) に対して個別の拡張メソッドを記述するのではなく、一般的な拡張メソッドを記述したいと考えています。

これは可能ですか?

ジェネリックメソッド用にこれまでに持っている(動作していない)コードは次のとおりです。

public static byte[] Foo<T>(this T input) where T : struct
{
    // error here, no match to overloads
    var result = BitConverter.GetBytes(input);
    // do more logic here...
    return result;
}

ちなみに、これは .NET 3.5 に準拠している必要があります。

4

2 に答える 2

3

BitConverter.GetBytes推奨されていませんが、メソッドを動的に呼び出すことができます。

public static byte[] ToFlipped<T>(T input) where T : struct
{
    var result = (byte[])typeof(BitConverter).GetMethod("GetBytes", new[] { typeof(T) })
        .Invoke(null, new[] { input });
    Array.Reverse(result);

    return result;
}
于 2016-08-17T20:54:45.450 に答える
3

GCHandle.Alloc() を使用し、構造体を固定します:-)

public static byte[] Foo<T>(this T input) where T : struct
{
  int size = Marshal.SizeOf(typeof(T));
  var result = new byte[size];
  var gcHandle = GCHandle.Alloc(input, GCHandleType.Pinned);
  Marshal.Copy(gcHandle.AddrOfPinnedObject(), result, 0, size);
  gcHandle.Free();
  return result;
}

...しかし、「Marshal.SizeOf」は bool と char に間違ったサイズを与えます。

SizeOf 関数を書き直しました (少しクレイジーに見えますが、非常に高速です)。

static readonly Dictionary<long, int> SizeOfDict = new Dictionary<long, int>();

//[MethodImpl(MethodImplOptions.AggressiveInlining)] // not supported below 4.5
public static int SizeOf<T>() where T : struct
{
  // --- Highspeed Compiler-Hack ---
  // if (typeof(T) == typeof(byte)) return sizeof(byte); // uncomment if .Net >= 4.5
  // if (typeof(T) == typeof(sbyte)) return sizeof(sbyte);
  // if (typeof(T) == typeof(ushort)) return sizeof(ushort);
  // if (typeof(T) == typeof(short)) return sizeof(short);
  // if (typeof(T) == typeof(uint)) return sizeof(uint);
  // if (typeof(T) == typeof(int)) return sizeof(int);
  // if (typeof(T) == typeof(ulong)) return sizeof(ulong);
  // if (typeof(T) == typeof(long)) return sizeof(long);
  // if (typeof(T) == typeof(float)) return sizeof(float);
  // if (typeof(T) == typeof(double)) return sizeof(double);
  // --- fix wrong sizes ---
  if (typeof(T) == typeof(char)) return sizeof(char);
  if (typeof(T) == typeof(bool)) return sizeof(bool);
  long id = (long)typeof(T).TypeHandle.Value;
  int len;
  if (!SizeOfDict.TryGetValue(id, out len))
  {
    len = Marshal.SizeOf(typeof(T));
    SizeOfDict.Add(id, len);
  }
  return len;
}
于 2016-08-17T22:36:39.960 に答える