[英]Converting `Int32` to `T` and `T []` to `Int32 []` in C#
我試圖編寫一個簡單的函數,該函數將使用RandomNumberGenerator類基於通用參數返回Int16
, Int32
或Int64
數組。
但是,無論我如何嘗試構建代碼,我似乎都無法擺脫從T []
到short/int/long []
的非法轉換,也無法IntXX
從IntXX
到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 []
轉換為IntXX []
?
您可以這樣做,從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));
}
我認為您在這里和過程中要變得聰明,使事情變得過於復雜。 只需編寫三個單獨的方法:
Int16[] GenerateRandomShorts()
Int32[] GenerateRandomInts()
Int64[] GenerateRandomLongs()
這里絕對沒有理由使用泛型,而您面臨的問題是逆流而行的結果。
只需使用非泛型重載,然后讓編譯器根據第一個參數的類型選擇要使用的重載:
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);
}
}
像最后一個這樣的另外兩個重載將處理int
和long
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.