我正在尝试创建以下功能:
public static byte[] ValueToBigEndian<T>(T data)
{
byte[] bytes;
// We want to use big endian
if (BitConverter.IsLittleEndian)
{
bytes = BitConverter.GetBytes(data).Reverse().ToArray();
//bytes.Take(System.Runtime.InteropServices.Marshal.SizeOf(data)); // probabl don't need this
}
else
{
// Host is big endian already
bytes = BitConverter.GetBytes(data;
//bytes.Take(System.Runtime.InteropServices.Marshal.SizeOf(data)); // probabl don't need this
}
return bytes;
}
所以我在这里使用的BitConverter.GetBytes(...)
不是通用的,但它有很多重载(ushort
,int
,bool
,ulong
,{{ 1}},long
等等......)。
我试图避免为每个函数编写匹配的重载函数,所以我的想法是使用泛型函数。恕我直言,这将运行正常,直到有人试图使用不在重载列表中的类型,然后编译器会抱怨。但是编译器立即抱怨,因为类型short
没有重载。
我得到的错误是
错误CS1503参数1:无法从'T'转换为'bool'
有没有办法实现我在这里尝试的目标?
答案 0 :(得分:3)
你得到这个的原因是因为价值类型不能被模板化。就个人而言,我认为这是C#失败,并且总是会导致重复,尽管开发人员对此有所说明。
您所能做的就是为每种值类型创建重载...
<强>更新强>
另一种更肮脏的方式是用反射来解决这个问题。您可以通过执行以下操作获得所需的方法:
public static byte[] GetBytesTemplated<T>(T value) where T : struct
{
var method = typeof(BitConverter).GetMethod("GetBytes", new[]{typeof(T)});
return (byte[])method.Invoke(null, new object[]{value});
}
但是,这样您需要自己检查模板的值类型。 您的最终代码将如下所示:
public static byte[] ValueToBigEndian<T>(T data) where T : struct
{
byte[] bytes = GetBytesTemplated(data);
// We want to use big endian
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return bytes;
}
答案 1 :(得分:1)
逻辑会说这可以做到。但是,除Object
的任何重载都接受作为参数时,所有值类型都没有公共类型(BitConverter.GetBytes
除外)。
您可以改为使用泛型参数而只是相信传递给方法的值是BitConverter.GetBytes
的有效参数类型之一:
public static byte[] ValueToBigEndian(dynamic data)
{
byte[] bytes = BitConverter.GetBytes(data);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return bytes;
}
我更喜欢这种方法而不是使用反射,因为它更容易理解发生了什么,我相信它也会运行得更快(未经测试的声明)。但是,像Reflection一样,您必须进行自己的类型检查以捕获传递不兼容类型的对象的情况。 (这可以通过试用来处理,但我不确定是否必须考虑这一点&#34;最佳实践&#34;。)