【发布时间】:2019-12-02 18:28:22
【问题描述】:
我一定遗漏了一些明显的东西,但我没有找到将Object[] 类型的数组转换为TE[] 类型的数组的直接方法,而TE 仅在运行时知道。
这是我正在努力实现的工作版本:
using System;
using System.Globalization;
using System.Linq;
namespace TestArrays
{
class Program
{
static T Parse<T>(string s)
{
T result;
if (typeof(T).IsArray)
{
var TE = typeof(T).GetElementType();
var rawResult = s.Split(',').Select(x => Convert.ChangeType(x, TE, CultureInfo.InvariantCulture)).ToArray();
result = (T)(object)Array.CreateInstance(TE, rawResult.Length);
Array.Copy(rawResult, (Array)(object)result, rawResult.Length);
}
else
{
result = (T)Convert.ChangeType(s, typeof(T), CultureInfo.InvariantCulture);
}
return result;
}
static void Main(string[] args)
{
Console.WriteLine(Parse<object>("abc"));
Console.WriteLine(Parse<string>("abc"));
Console.WriteLine(Parse<int>("123456"));
Console.WriteLine(Parse<double>("123.456"));
Console.WriteLine(Parse<object[]>("a,b,c"));
Console.WriteLine(Parse<string[]>("a,b,c"));
Console.WriteLine(Parse<int[]>("123,456,789"));
Console.WriteLine(Parse<double[]>("123.456,456.789,789.101112"));
}
}
}
我想将 Object[] 类型的 rawResult 转换为预期的返回类型 TE[]。
我知道直接转换并不总是可行的,因为数组元素的大小可能会有所不同。
但在这里我想转换为另一种引用类型,这样就可以就地完成,而不必创建新数组并分配相同数量的内存。
此外,可以保留元素,因为它们已经是目标 TE 类型的引用。
我见过Array.ConvertAll,但它也会返回Object[]。
【问题讨论】:
-
这是一个奇怪的要求。你有没有仔细考虑过这是否真的是你想要做的?我会考虑使用像 JSON 这样的标准序列化/反序列化格式,并利用框架来处理转换。
-
具体用例是 .NET Core 配置 API,它返回一些
object[]我想转换为特定的T[]。无论如何,现在我想知道。 :) -
所以配置 API 返回一个
object[]并且您碰巧知道,在您的特定情况下,该数组中应该只有ints 吗?这是一个非常不同的问题,而且更容易解决。使用 LINQvar intArray = objectArray.Cast<int>().ToArray(); -
调用者知道,它调用的不是我自己的通用函数
T Get<T>(string configParamPath)。 :) -
调用者可以相对轻松地调用
Get<object[]>().Cast<int>()。这很简单,不需要反思。或者,您可以创建一个GetArray<T>()辅助方法,该方法在内部传递到Get<object[]>().Cast<T>().ToArray()。由于框架已经创建了一个object[],因此您无法避免分配另一个数组,除非您愿意返回类似IEnumerable<>的内容。