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#使用泛型函数将参数传递给具有许多重载的函数

出现这种情况的原因是值类型不能被模板化。就我个人而言,我认为这是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来处理,但我不确定这是否一定会被认为是"最佳实践"。)