c#使用泛型函数将参数传递给具有许多重载的函数
本文关键字:函数 许多 重载 参数传递 泛型 | 更新日期: 2023-09-27 18:16:56
我想创建以下函数:
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
, long
, short
等…)。
我试图避免为每一个都编写匹配的重载函数,所以我的想法是使用泛型函数。恕我直言,这将运行良好,直到有人试图使用重载列表中没有的类型,然后编译器会抱怨。但是编译器立即报错,因为没有针对T
类型的重载。
错误CS1503参数1:不能从'T'转换为'bool'
有办法实现我在这里尝试的吗?
出现这种情况的原因是值类型不能被模板化。就我个人而言,我认为这是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;
}
逻辑上会说这是可以做到的。然而,没有一种通用类型(除了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一样,您必须自己进行类型检查,以捕捉传递不兼容类型的对象的情况。(这可以通过try-catch来处理,但我不确定这是否一定会被认为是"最佳实践"。)