c#使用泛型函数将参数传递给具有许多重载的函数
我正在尝试创建以下函数:c#使用泛型函数将参数传递给具有许多重载的函数,c#,templates,generics,C#,Templates,Generics,我正在尝试创建以下函数: public static byte[] ValueToBigEndian<T>(T data) { byte[] bytes; // We want to use big endian if (BitConverter.IsLittleEndian) { bytes = BitConverter.GetBytes(data).Reverse().ToAr
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;
}
公共静态字节[]值ToBigendian(T数据)
{
字节[]字节;
//我们想用big-endian
if(位转换器.IsLittleEndian)
{
bytes=BitConverter.GetBytes(数据).Reverse().ToArray();
//bytes.Take(System.Runtime.InteropServices.Marshal.SizeOf(data));//probabl不需要这个
}
其他的
{
//主持人已经是大端人了
字节=位转换器.GetBytes(数据;
//bytes.Take(System.Runtime.InteropServices.Marshal.SizeOf(data));//probabl不需要这个
}
返回字节;
}
所以我在这里使用的是BitConverter.GetBytes(…)
,它不是泛型的,但是它有很多重载(ushort
,int
,bool
,ulong
,long
,short
,等等)
我试图避免为每种类型编写匹配的重载函数,因此我的想法是使用泛型函数。在有人尝试使用重载列表中不包含的类型之前,这将正常运行,然后编译器会抱怨。但是编译器会立即抱怨,因为类型T
没有重载
我得到的错误是
错误CS1503参数1:无法从“T”转换为“bool”
有什么方法可以实现我在这里所尝试的吗?之所以会出现这种情况,是因为无法对值类型进行模板化。我个人认为,这是C#fail,不管开发人员怎么说,它总是会导致重复 您所能做的就是为每个值类型创建重载 更新 另一种更肮脏的方法是通过反射来解决这个问题。通过这样做,您实际上可以获得所需的方法:
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});
}
公共静态字节[]GetBytesTemplated(T值),其中T:struct
{
var method=typeof(BitConverter).GetMethod(“GetBytes”,new[]{typeof(T)});
return(byte[])method.Invoke(null,新对象[]{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;
}
公共静态字节[]值ToBigendian(T数据),其中T:struct
{
字节[]字节=GetBytesTemplated(数据);
//我们想用big-endian
if(位转换器.IsLittleEndian)
{
Array.Reverse(字节);
}
返回字节;
}
之所以会出现这种情况,是因为无法对值类型进行模板化。就我个人而言,我认为这是C#fail,不管开发人员怎么说,它总是会导致重复
您所能做的就是为每个值类型创建重载
更新
另一种更肮脏的方法是通过反射来解决这个问题。通过这样做,您实际上可以获得所需的方法:
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});
}
公共静态字节[]GetBytesTemplated(T值),其中T:struct
{
var method=typeof(BitConverter).GetMethod(“GetBytes”,new[]{typeof(T)});
return(byte[])method.Invoke(null,新对象[]{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;
}
公共静态字节[]值ToBigendian(T数据),其中T:struct
{
字节[]字节=GetBytesTemplated(数据);
//我们想用big-endian
if(位转换器.IsLittleEndian)
{
Array.Reverse(字节);
}
返回字节;
}
逻辑将说明这是可以完成的。但是,没有任何通用类型(除了对象
)可以从该类型继承任何重载的位转换器。GetBytes
可以接受为参数
您可以改为使用泛型参数,只需相信传递到方法中的值是BitConverter.GetBytes
的有效参数类型之一:
public static byte[] ValueToBigEndian(dynamic data)
{
byte[] bytes = BitConverter.GetBytes(data);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return bytes;
}
与使用反射相比,我更喜欢这种方法,因为它更容易理解正在发生的事情,而且我相信它也会运行得更快(未经测试的声明)。然而,与反射一样,当传递不兼容类型的对象时,您必须进行自己的类型检查。(这可以通过try-catch来处理,但我不确定这是否一定会被视为“最佳实践”。逻辑将声明这可以完成。但是,没有任何通用类型(除了
对象
)是所有值类型继承自位转换器的任何重载。GetBytes
将接受为参数
您可以改为使用泛型参数,只需相信传递到方法中的值是BitConverter.GetBytes
的有效参数类型之一:
public static byte[] ValueToBigEndian(dynamic data)
{
byte[] bytes = BitConverter.GetBytes(data);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return bytes;
}
与使用反射相比,我更喜欢这种方法,因为它更容易理解正在发生的事情,而且我相信它也会运行得更快(未经测试的声明)。然而,与反射一样,当传递不兼容类型的对象时,您必须进行自己的类型检查。(这可以通过try-catch来处理,但我不确定这是否一定是“最佳实践”。您不能这样做,编译器需要知道
t
可以是什么,以便解决对GetBytes
的调用。因为t
可以是任何类型(从签名中),也可以使用对象
或任何其他类型,而GetBytes
没有这样的重载。因此,我猜您想做的是不可能的,并且您一直在使用重载。您不能这样做,编译器需要知道t
可以是什么,以便将对GetBytes
的调用解析为te> 可以是任何类型(从签名中),也可以是对象
或任何其他类型,但是GetBytes
没有这种重载。因此我猜你想做的是不可能的,你被卡住了