我需要帮助来理解抽象类的用法。我有一个名为WorldObject
的抽象类:
public abstract class WorldObject
{
public Vector3 position;
}
我有许多继承自此的类,例如Building
和Tree
。
我想创建一种方法,该方法遍历List
的{{1}},然后返回最接近我的方法。
我希望能够对所有类型的WorldObjects
使用此方法,但无法使其正常工作:
WorldObjects
当我尝试将public List<Building> buildings = new List<Building>();
public List<Tree> trees= new List<Tree>();
private void GoToClosestBuilding()
{
var target = GetClosestWorldObject(buildings); //Error: Cannot convert building to WorldObject
}
Vector3 GetClosestWorldObject(List<WorldObject> objects)
{
//...
}
或Building
列表传递给我的方法时,它返回错误,无法在Tree
和Building
之间转换,依此类推。
如何构造代码,使类似的代码行得通?
答案 0 :(得分:6)
List<Building>
与List<WorldObject>
的分配不兼容,因为那样您就可以这样做
List<WorldObject> worldObjects = buildings; // Not possible!
worldObjects.Add(tree); // Legal
worldObjects.Add(tree);
是完全合法的。但是,由于worldObjects
会引用建筑物列表,因此您不能将其添加为树!
但是,您可以将方法的签名更改为
Vector3 GetClosestWorldObject(IEnumerable<WorldObject> objects)
{
...
}
现在可以了
var target = GetClosestWorldObject(buildings);
因为可枚举被声明为
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
out
关键字指出T
仅出现在外位置,即作为返回值或外参数。这使类型成为协变。
答案 1 :(得分:1)
您可以使用通用函数。
Vector3 GetClosestWorldObject<T>(List<T> objects) where T: WorldObject
{
// ...
}
其他答案提到的问题是List<WorldObject>
与List<Building>
不同。如果要将List
传递给参数而不是IEnumerable
,则可以使用通用函数,该函数采用List
中的T
,其中T
是WorldObject
。现在T
已分配给Building
,List<Building>
是可以接受的。