1
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;
        }
    }
}
4

2 回答 2

10

你需要这样做:

return buildings.OfType<T>.ToArray();

下面解释了为什么您的尝试没有奏效。

表达式的类型buildings.FindAll(x => x is T)List<Building>。这是因为buildings它本身是一个List<Building>, 并且FindAll不会神奇地改变返回值中项目的类型。因此,ToArray()产生一个Building[].

运算符仅在直接强制转换有效的情况下as返回非空值。由于从Building[]to的转换Home[]是无效的,所以as总是产生null. 不要对将 a 转换Home[]为 aBuilding[]是有效的事实感到困惑。

于 2013-05-20T07:58:34.117 回答
7

问题是 aBuilding[]不是 a Home[]。所以这段代码:

public T[] FindBuildings<T>() {       
    return buildings.FindAll(x => x is T).ToArray() as T[];
}

...总是试图将 aBuilding[]视为 a T[],并T[]Tis notBuilding或时返回Object。您需要先创建一个T[]。幸运的是,LINQ 实际上使这对您来说非常容易:

public T[] FindBuildings<T>() {       
    return buildings.OfType<T>().ToArray();
}

这件重要的事情是OfType<T>返回一个IEnumerable<T>- 而你的调用List<Building>.FindAll仍然返回 a List<Building>,所以ToArray创建一个Building[].

顺便说一句,我完全建议使用强制转换而不是as除非它有效返回asnull。如果您希望强制转换失败成为错误条件,则直接强制转换指示立即通过异常,而不是您NullReferenceException稍后得到,从而掩盖原始问题。

于 2013-05-20T08:00:27.103 回答