在C#中将`Int32`转换为`T`和`T []`到`Int32 []`

时间:2013-10-07 12:34:07

标签: c# .net arrays generics casting

我试图编写一个简单的函数,它将使用RandomNumberGenerator类根据泛型参数返回Int16Int32Int64的数组。

但是,无论我如何尝试构建代码,我似乎无法通过从T []short/int/long []的非法转换,也无法从IntXX转换为{{1 }}。请参阅以下代码中的两条评论。

似乎我错过了一个基本的构造,可以解决这个问题。有什么想法吗?

T

另外,在不使用流和二进制阅读器的情况下,是否有更有效的方法将public static void GenerateRandom<T> (T [] data, bool nonZeroOnly = false) where T: struct, System.IComparable, System.IFormattable, System.IConvertible { int size = 0; byte [] bytes = null; if ((typeof(T) != typeof(byte)) && (typeof(T) != typeof(short)) && (typeof(T) != typeof(int)) && (typeof(T) != typeof(long))) { throw (new System.ArgumentException("This method only accepts types [Byte], [Int16], [Int32], or [Int64].", "<T>")); } if (typeof(T) == typeof(byte)) { using (System.Security.Cryptography.RandomNumberGenerator generator = System.Security.Cryptography.RandomNumberGenerator.Create()) { // Invalid cast (implicit or explicit) from T [] to byte []. if (nonZeroOnly) { generator.GetNonZeroBytes(data); } else { generator.GetBytes(data); } } } else { size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); bytes = new byte [data.Length * size]; using (System.Security.Cryptography.RandomNumberGenerator generator = System.Security.Cryptography.RandomNumberGenerator.Create()) { if (nonZeroOnly) { generator.GetNonZeroBytes((byte []) System.Convert.ChangeType(data, typeof(byte []))); } else { generator.GetBytes((byte []) System.Convert.ChangeType(data, typeof(byte []))); } } using (System.IO.MemoryStream stream = new System.IO.MemoryStream(bytes)) { using (System.IO.BinaryReader reader = new System.IO.BinaryReader(stream)) { // Invalid cast (implicit or explicit) from short/int/long to T. if (typeof(T) == typeof(short)) { for (int i=0; i<bytes.Length; i+=size) { data[i] = reader.ReadInt16(); } } else if (typeof(T) == typeof(int)) { for (int i=0; i<bytes.Length; i+=size) { data[i] = reader.ReadInt32(); } } else if (typeof(T) == typeof(long)) { for (int i=0; i<bytes.Length; i+=size) { data[i] = reader.ReadInt64(); } } } } } } 转换为byte []

3 个答案:

答案 0 :(得分:3)

您可以执行此操作,从int转到T

void Foo<T>(T[] data)
{
    ...
    int v = r.Next(255);  // limit to byte.max for simplicity
    data[i] = (T) Convert.ChangeType(v, typeof(T));
}

答案 1 :(得分:2)

我认为你想在这里变得聪明,并且在这个过程中让事情变得太复杂。只需编写三个单独的方法:

Int16[] GenerateRandomShorts()
Int32[] GenerateRandomInts()
Int64[] GenerateRandomLongs()

答案 2 :(得分:1)

这里绝对没有理由使用仿制药,而你遇到的问题是与当前游泳相关的问题。

只需使用非泛型重载,让编译器根据第一个参数的类型选择要使用的重载:

public static void GenerateRandom(byte[] data, bool nonZeroOnly = false)
{
    using (var generator = RandomNumberGenerator.Create())
    {
        if (nonZeroOnly) { generator.GetNonZeroBytes(data); }
        else { generator.GetBytes(data); }
    }
}

public static void GenerateRandom(short[] data, bool nonZeroOnly = false)
{
    var size = sizeof(short);
    var bytes = new byte[data.Length * size];

    GenerateRandom(bytes, nonZeroOnly);

    for (var i = 0; i < data.Length; ++i) {
        data[i] = BitConverter.ToInt16(bytes, i * size);
    }
}

最后一次重载会导致intlong