class Building {
}
class Home: Building {
}
private List<Building> buildings;
public T[] FindBuildings<T>() {
return buildings.FindAll(x => x is T).ToArray() as T[];
}
我有一个列表可以保存地图上的所有建筑物,并编写一个功能来查找特定的建筑类型。
我希望使用FindBuildings<Home>()
来获取包含地图上所有住宅建筑的数组,但是当我运行代码时,我发现函数总是返回null,似乎as
不起作用。这是否意味着as
无法使用泛型类型参数?
所以,我改变了代码:
private List<Building> buildings;
public Building[] FindBuildings<T>() {
return buildings.FindAll(x => x is T).ToArray();
}
使用FindBuildings<Home>() as Home[]
访问地图上的住宅楼宇。但是......它仍然是空的。
我看到了一个Unity3d的例子,告诉我使用'as'转换数组类型,为什么我失败了?
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
void OnMouseDown() {
HingeJoint[] hinges = FindObjectsOfType(typeof(HingeJoint)) as HingeJoint[];
foreach (HingeJoint hinge in hinges) {
hinge.useSpring = false;
}
}
}
答案 0 :(得分:10)
你需要这样做:
return buildings.OfType<T>.ToArray();
解释为什么你的尝试不起作用。
表达式buildings.FindAll(x => x is T)
的类型为List<Building>
。这是因为buildings
本身是List<Building>
,FindAll
并没有神奇地改变返回值中项目的类型。因此,ToArray()
生成Building[]
。
as
运算符仅在直接转换有效的情况下返回非空值。由于Building[]
到Home[]
的广告无效,as
始终会生成null
。不要因将Home[]
转换为Building[]
这一事实而感到困惑。
答案 1 :(得分:7)
问题是Building[]
不是Home[]
。所以这段代码:
public T[] FindBuildings<T>() {
return buildings.FindAll(x => x is T).ToArray() as T[];
}
...始终尝试将Building[]
视为T[]
,并在T[]
既不是T
也不Building
时返回Object
}。您需要创建T[]
才能开始。幸运的是,LINQ实际上让你很容易:
public T[] FindBuildings<T>() {
return buildings.OfType<T>().ToArray();
}
重要的是,OfType<T>
会返回IEnumerable<T>
- 而您对List<Building>.FindAll
的回复仍然会返回List<Building>
,因此ToArray
正在创建{ {1}}。
顺便说一句,我建议使用强制转换代替Building[]
,除非{em} as
返回null。如果您希望转换失败为错误条件,则直接转换表示通过异常立即,而不是稍后获得as
,掩盖原始问题。