如果我在编译时知道类型或者它是一个通用参数,这将是非常简单的,因为我可以做类似myArray.Cast<T>()
的事情但实际上我实际拥有的是这个。我没有已知的类型或通用参数。我有一个System.Type
变量。
// could actually be anything else
Type myType = typeof(string);
// i already know all the elements are the correct types
object[] myArray = new object[] { "foo", "bar" };
我能做一些反射魔法来获得包含相同数据的string[]
引用吗? (编译时不知道string
)
答案 0 :(得分:26)
这不是真正的演员(我正在分配一个新阵列并复制原件),但也许这可以帮到你?
Type myType = typeof(string);
object[] myArray = new object[] { "foo", "bar" };
Array destinationArray = Array.CreateInstance(myType, myArray.Length);
Array.Copy(myArray, destinationArray, myArray.Length);
在此代码中,destinationArray
将是string[]
的实例(或myType
的任何类型的数组)。
答案 1 :(得分:2)
您无法执行此类强制转换,因为数组object []和string []实际上是不同的类型且不可转换。但是,如果要将不同的此类型传递给函数,只需将参数设置为IEnumerable即可。然后,您可以传递任何类型的数组,任何类型的列表等。
// Make an array from any IEnumerable (array, list, etc.)
Array MakeArray(IEnumerable parm, Type t)
{
if (parm == null)
return Array.CreateInstance(t, 0);
int arrCount;
if (parm is IList) // Most arrays etc. implement IList
arrCount = ((IList)parm).Count;
else
{
arrCount = 0;
foreach (object nextMember in parm)
{
if (nextMember.GetType() == t)
++arrCount;
}
}
Array retval = Array.CreateInstance(t, arrCount);
int ix = 0;
foreach (object nextMember in parm)
{
if (nextMember.GetType() == t)
retval.SetValue(nextMember, ix);
++ix;
}
return retval;
}
答案 2 :(得分:2)
这不是一个班轮,但可以用两行完成。给定您指定的Array
类型正确的元素myArray
和指定的Type
参数myType
,可以动态调用.Cast<"myType">.ToArray()
。
var typeConvertedEnumerable = typeof(System.Linq.Enumerable)
.GetMethod("Cast", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(new Type[] { myType })
.Invoke(null, new object[] { myArray });
var typeConvertedArray = typeof(System.Linq.Enumerable)
.GetMethod("ToArray", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(new Type[] { myType })
.Invoke(null, new object[] { typeConvertedEnumerable });
虽然方法生成比直接调用慢,但数组大小为O(1)。这种方法的好处是,如果IEnumerable<"myType">
可以接受,则不需要第二行,因此我不相信该数组将被复制。
答案 3 :(得分:1)
您必须手动浏览每个对象,在它们之间获取最通用的公共类型,然后创建该类型的新数组并复制元素。没有任何一个班轮。
答案 4 :(得分:1)
这将创建你想要的数组,但我不知道你之后会用它做什么,因为编译器仍然不知道数组对象的类型是什么。
Type myType = typeof(string);
object[] myArray = new object[] { "foo", "bar" };
Array myArrayOfTheCorrectType = Array.CreateInstance(myType, myArray.Length);
for (int index = 0; index < myArray.Length; index++)
myArrayOfTheCorrectType.SetValue(myArray[index], index);
答案 5 :(得分:1)
我会说答案是不能演员。我知道很多其他人都提供了解决方案,但答案是肯定的。我认为原因是因为数组的类型是object,它低于string。除非您手动执行,否则编译器不会发生上转换。我也玩过DLR的东西,但它仍然把它当作对象。
class Program
{
static void Main(string[] args)
{
// could actually be anything else
Type myType = typeof(string);
Type myArrayType = Array.CreateInstance(myType, 1).GetType();
// i already know all the elements are the correct types
object[] myArray = new object[] { "foo", "bar" };
MethodInfo castMethod = typeof(Program).GetMethod("Cast").MakeGenericMethod(myArrayType);
object castedObject = castMethod.Invoke(null, new object[] { myArray });
}
public static T Cast<T>(object o)
{
return (T)o;
}
}