如何将泛型类与相同泛型类型的另一个泛型类的字段一起使用?

问题描述 投票:0回答:1

我想实现一组类,可以与 UInt16 和 UInt32 类型参数一起使用。

第一个表示电报的标头,可以与 UInt32 和 UInt64 数据类型一起使用。

任何非必需字段已被省略!

public class Header<T> // where T : struct, IConvertible
{
    public Header(T off, T len)
    {
        Offset = off;
        LenData = len;
    }
    public T Offset;
    public T LenData;
    public byte[] ToByteArray()
    {
        byte[] bTemp = new byte[2 * Marshal.SizeOf(typeof(T))];
        if (Offset is UInt16)
        {
            Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(Offset)), 0, bTemp, 0, Marshal.SizeOf(typeof(T)));
            Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(LenData)), 0, bTemp, Marshal.SizeOf(typeof(T)), Marshal.SizeOf(typeof(T)));
        }
        else if (Offset is UInt32)
        {
            Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(Offset)), 0, bTemp, 0, Marshal.SizeOf(typeof(T)));
            Array.ConstrainedCopy(System.BitConverter.GetBytes(Convert.ToUInt16(LenData)), 0, bTemp, Marshal.SizeOf(typeof(T)), Marshal.SizeOf(typeof(T)));
        }
        else
        {
            throw new NotSupportedException("Type " + Offset.GetType() + "not supported");
        }

        return bTemp;
    }
}

这个类为我提供了一个电报头的字节数组(T = UInt16 为 2 + 2 个字节,T = UInt32 为 4 + 4 个字节)。

现在我需要另一个类,它使用标头类来构建电报的字节数组:

class Telegram<T>
{
    public Header<T> header;
    public Telegram(T offset, byte[] bData)
    {
        header = new Header<T>(offset,bData.Length)
    }
}

该类本身可以按预期工作:

static void Main(string[] args)
{
    byte[] bData = new byte[16];
    // This call works
    Header<UInt16> ui16Header = new Header<ushort>(12345, (ushort)bData.Length);
    byte[] b0 = ui16Header.ToByteArray();

b0 包含所需的电报内容...

然后我想创建两个电报(对于两种支持的数据类型:

    // These calls don't work (because of compile error, or
    // because of a thrown exception - see below)
    Telegram<UInt16> telegram16 = new Telegram<ushort>(7000, bData);
    Telegram<UInt32> telegram32 = new Telegram<uint>(70000, bData);
}

上面的类 Telegram 的构造函数无法编译(无法将 int 转换为 T)。

修改构造函数如下,即可编译:

    public Telegram(T offset, byte[] bData)
    {
        object ot = bData.Length;
        T len = (T)ot;
        header = new Header<T>(offset, len);
    }

但这会导致运行时异常。

这个问题能解决吗?我知道,我可以简单地编写两个包含所有类型特定方法本身的类,但只有标头中的字段是 UInt16 或 UInt32

或者这会是使用继承和接口的更简单的方法吗?

c# generics
1个回答
0
投票

您可以使用新的

INumber
等界面。

这允许您与字节数组进行转换,以及与其他整数或数字类型进行转换。

public class Header<T> where T : struct, IBinaryInteger<T>
{
    public Header(T off, T len)
    {
        Offset = off;
        LenData = len;
    }

    public T Offset;
    public T LenData;

    public byte[] ToByteArray()
    {
        var size = Offset.GetByteCount();
        byte[] bTemp = new byte[2 * size];
        Offset.WriteLittleEndian(bTemp);
        LenData.WriteLittleEndian(bTemp, size);
        return bTemp;
    }
}

public class Telegram<T> where T : struct, IBinaryInteger<T>
{
    public Header<T> header;
    public Telegram(T offset, byte[] bData)
    {
        header = new Header<T>(offset, T.CreateTruncating(bData.Length))
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.