我有两种方法:
Foo[] GetFoos(Type t) { //do some stuff and return an array of things of type T }
T[] GetFoos<T>()
where T : Foo
{
return GetFoos(typeof(T)) as T[];
}
但是,这似乎总是返回null。我做错了还是这只是C#的缺陷?
的Nb: 我知道我可以用以下方法解决这个问题:
GetFoos(typeof(T)).Cast<T>().ToArray();
但是,我更愿意做任何分配(在对垃圾收集非常敏感的环境中工作)。
铌++: 如果您建议替代非分配解决方案,则可获得奖励
编辑: 这提出了一个有趣的问题。这里的MSDN文档:http://msdn.microsoft.com/en-us/library/aa664572%28v=vs.71%29.aspx表示如果存在隐式或显式转换,则转换将成功。在这种情况下,有一个显式的强制转换,因此强制转换应该成功。 MSDN文档是错误的吗?
答案 0 :(得分:2)
不,C#强制转换并非无用 - 您只是无法将Foo[]
强制转换为T[]
T
,其中Foo[]
是更多派生类型,T
可能包含与GetFoos
不同的其他元素。为什么不将GetFoos<T>()
方法调整为Type
?只接受new T[]
对象的方法可以很容易地转换为通用方法,您可以通过Count
直接创建数组。
如果这是不可能的:你是否需要数组提供的能力(即索引和IEnumerable<T>
之类的东西)?如果没有,您可以使用Cast<T>.ToArray()
而不会出现太多问题。如果不是:你不会绕过Foo[]
方式。
编辑:
从T[]
到T[]
无法进行投射,您的链接中的描述则相反 - 您可以将Foo[]
投射到T
全部Foo
为Foo
,但并非所有T
均为{{1}}。
答案 1 :(得分:1)
如果您可以安排GetFoos
使用new T[]
创建返回数组,那么您就赢了。如果你使用了new Foo[]
,那么数组的类型就固定了,无论它实际拥有的对象类型如何。
答案 2 :(得分:0)
我没试过这个,但它应该有效:
T[] array = Array.ConvertAll<Foo, T>(input,
delegate(Foo obj)
{
return (T)obj;
});
您可以在http://msdn.microsoft.com/en-us/library/exc45z53(v=VS.85).aspx
找到更多信息我认为这会就地转换,所以它不会进行任何重新分配。
答案 3 :(得分:0)
根据我的理解,使用System.Array
代替更具体的数组可以帮助您。请记住,Array
是所有强类型数组的基类,因此Array
引用实际上可以存储任何数组。你应该制作你的(通用?)字典映射Type -> Array
,这样你就可以存储任何强类型数组,而不必担心需要将一个数组转换为另一个数组,现在它只是类型转换。
即,
Dictionary<Type, Array> myDict = ...;
Array GetFoos(Type t)
{
// do checks, blah blah blah
return myDict[t];
}
// and a generic helper
T[] GetFoos<T>() where T: Foo
{
return (T[])GetFoos(typeof(T));
}
// then accesses all need casts to the specific type
Foo[] f = (Foo[])GetFoos(typeof(Foo));
DerivedFoo[] df = (DerivedFoo[])GetFoos(typeof(DerivedFoo));
// or with the generic helper
AnotherDerivedFoo[] adf = GetFoos<AnotherDerivedFoo>();
// etc...
p.s。,您提供的MSDN链接显示了数组的协变性。也就是说,您可以在对基类型数组的引用中存储更多派生类型的数组。你在这里想要实现的是逆变(即,使用基类型的数组代替更多派生类型的数组),这是另一种方式,没有进行转换,数组不能做什么。 / p>