c#使用泛型函数将参数传递给具有许多重载的函数

时间:2016-11-08 07:16:29

标签: 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().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(...)不是通用的,但它有很多重载(ushortintboolulong,{{ 1}},long等等......)。

我试图避免为每个函数编写匹配的重载函数,所以我的想法是使用泛型函数。恕我直言,这将运行正常,直到有人试图使用不在重载列表中的类型,然后编译器会抱怨。但是编译器立即抱怨,因为类型short没有重载。

我得到的错误是

  

错误CS1503参数1:无法从'T'转换为'bool'

有没有办法实现我在这里尝试的目标?

2 个答案:

答案 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;。)