使用抽象类作为函数参数

Gre*_*aue 4 c#

我需要帮助来理解抽象类的用法。我有一个抽象类,称为WorldObject

public abstract class WorldObject
{
    public Vector3 position;
}
Run Code Online (Sandbox Code Playgroud)

我有许多继承自此的类,例如BuildingTree

我想创建一个循环通过的List方法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)
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

当我尝试将我的BuildingTree列表传递给我的方法时,它返回一个错误,无法在Building和之间转换WorldObject,依此类推。

如何构造代码,使类似的代码有效?

Oli*_*bes 6

A List<Building>与a不兼容,List<WorldObject>因为这样您就可以

List<WorldObject> worldObjects = buildings; // Not possible!
worldObjects.Add(tree); // Legal
Run Code Online (Sandbox Code Playgroud)

worldObjects.Add(tree);是完全合法的。但是,就像worldObjects引用建筑物列表一样,您将不能将其添加为树!

但是,您可以将方法的签名更改为

Vector3 GetClosestWorldObject(IEnumerable<WorldObject> objects)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在,这有效

var target = GetClosestWorldObject(buildings);
Run Code Online (Sandbox Code Playgroud)

因为可枚举被声明为

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

out关键字的状态T只发生在出仓,即作为返回值,或者输出参数。这使得类型是协变的。

另请参见:- 协方差和协方差(C#)-Microsoft文档