发现“模糊匹配”

时间:2012-01-22 16:58:01

标签: c# reflection

我一直在尝试重新创建BitConverter.GetBytes。但是,应允许传递每种值类型。然后,该方法应检测其类型(Int32,Int16,Byte等)并动态调用相应的BitConverter.GetBytes方法。我的尝试是使用反射。 这就是我的代码:

public static class BitConverterExtensions
{

    public static byte[] GetBytes(ValueType obj)
    {
        Type tObj = obj.GetType();
        Type tBitConverter = typeof(BitConverter);
        Type tSelf = typeof(BitConverterExtensions);

        MethodInfo miGetBytes = tBitConverter.GetMethod("GetBytes", new Type[] { tObj });

        byte[] result = (byte[])miGetBytes.Invoke(null, new object[] { obj });
        return result;
    }

}

如果我通过注,长,浮动,双打,布尔等,它的效果很好。 唯一不起作用的是传递一个字节。如果传递了一个字节,则抛出AmbiguousMatchException。但是,我看不到任何与

具有相同签名的方法
byte[] GetBytes(byte)

我做错了什么,为什么只有传递一个字节才能正常工作? 这就是我如何调用该方法:

byte[] result = BitConverterExtensions.GetBytes((byte)123);

4 个答案:

答案 0 :(得分:2)

问题是BitConverter.GetBytes()没有接受byte的重载。它认识到这一点,因此尝试将byte推广到可以使用的public static byte[] GetBytes(ValueType obj) { Type tObj = obj.GetType(); Type tBitConverter = typeof(BitConverter); if (tObj == typeof(byte)) return new byte[] { (byte)obj }; MethodInfo miGetBytes = tBitConverter.GetMethod("GetBytes", new Type[] { tObj }); return (byte[])miGetBytes.Invoke(null, new object[] { obj }); } 。然而,有许多不同的候选人可以被提升到因此模糊性错误。您可能需要针对该类型的特殊情况将您自己的参数抛出到单独的字节数组中。

{{1}}

答案 1 :(得分:1)

如果BitConverter没有字节签名,那么您的代码将无效。如果你能这样做,我就会徘徊:

if(tobj == typeof(byte))
    return new byte[]{(byte)obj};

所以你将返回一个字节[1],其值为(一个字节,对吗?)

答案 2 :(得分:0)

反思会使你的代码效率低下。由于BitConverter.GetBytes只有10个重载,为什么不直接为每个?

定义扩展方法
public static class BitConverterExtensions
{
    public static byte[] GetBytes(this bool value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this char value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this double value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this float value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this int value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this long value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this short value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this uint value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this ulong value)
    {
        return BitConverter.GetBytes(value);
    }
    public static byte[] GetBytes(this ushort value)
    {
        return BitConverter.GetBytes(value);
    }
}

然后,在您的客户端代码中:

byte[] intBytes = (44).GetBytes();     // gives a 4-byte array
byte[] longBytes = (44L).GetBytes();   // gives an 8-byte array

答案 3 :(得分:0)

因为对于这样一个受约束的问题,使用反射似乎有些过分,为什么不做类似的事情:

public static byte[] GetBytesFrom( object o )
{
  Type t = o.GetType() ;
  TypeCode tc = Type.GetTypeCode(t) ;
  byte[] bytes ;

  switch( tc )
  {
  case TypeCode.Boolean  : bytes = BitConverter.GetBytes( (bool)   o ) ; break ;
  case TypeCode.Char     : bytes = BitConverter.GetBytes( (char)   o ) ; break ;
  case TypeCode.Double   : bytes = BitConverter.GetBytes( (double) o ) ; break ;
  case TypeCode.Single   : bytes = BitConverter.GetBytes( (float)  o ) ; break ;
  case TypeCode.Int16    : bytes = BitConverter.GetBytes( (short)  o ) ; break ;
  case TypeCode.Int32    : bytes = BitConverter.GetBytes( (int)    o ) ; break ;
  case TypeCode.Int64    : bytes = BitConverter.GetBytes( (long)   o ) ; break ;
  case TypeCode.UInt16   : bytes = BitConverter.GetBytes( (ushort) o ) ; break ;
  case TypeCode.UInt32   : bytes = BitConverter.GetBytes( (uint)   o ) ; break ;
  case TypeCode.UInt64   : bytes = BitConverter.GetBytes( (ulong)  o ) ; break ;
  // not directly supported by BitConverter, but just for kicks, we'll throw it in.
  case TypeCode.SByte    : bytes = new []{ (byte)o }                   ; break ;
  case TypeCode.Byte     : bytes = new []{ (byte)o }                   ; break ;
  default : throw new InvalidOperationException("Can't get bytes from type {0}" , t.
  }
  return bytes ;
}