C# 访问从基础 class 列表继承 class 属性

C# Access inherited class properties from list of base class

首先,我创建基础 class 并继承 class

public class Entity
{
   public int EntityID;
   public EntityType type = EntityType.NONE;
}

public class EntityObject : Entity
{
   public Vector2 position;
   public EntityObject()
   {
      position = Vector2.Zero;
      type = EntityType.OBJECT;
   }
}

然后我创建基列表 class 来存储所有继承的 class

List<Entity> entityList = new List<Entity>();
entityList.Add(new EntityObject());

稍后,我尝试访问列表

中继承class的成员
for(int i = 0; i < entityList.Count; i++)
    if(entityList[i].type == EntityType.OBJECT)
        entityList[i].position = Vector2.One;

是的,我得到一个错误:'Entity' 不包含 'position' 的定义并且没有扩展方法 'position' 接受类型 'Entity' 的第一个参数可能是找到(您是否缺少 using 指令或程序集引用?)

是否有一种可能的方法来访问基 class 列表中继承的 class 属性?

您需要将Entity实例转换为EntityObject实例,因为Position字段确实不是Entity

的一部分

所以:

var entityObjectInEntityList = (EntityObject)entityList[0]

将为您提供正确的类型,然后您可以根据该类型访问 .Position 字段。


如评论中所述,您还可以通过以下方式测试类型/进行转换:

if(entityList[0] is EntityObject)

Just testing type - usually avoided as you still need to cast to get the correct type and that involves overhead

var item = entityList[0] as EntityObject;
if (item != null)
{
   var position = item.Position;
}

或使用 C# 6

var position = (entityList[0] as EntityObject)?.Position;

Using the as keyword to perform a cast, and return a null if it fails.


出于仁慈的考虑,正如 Henk 所指出的,您显然是在尝试以 EntityType 属性 的形式在 class 中包含一些类型信息.

您可以在运行时确定对象的类型:

var type = instance.GetType();

因此:

if(itemInList.GetType() == typeof(EntityObject))

会告诉您实例的类型,但是使用派生 classes 的类型检查之类的东西通常是一种味道。

假设您不需要 Entity 上的任何基本功能,我建议您改用界面方法。

我建议看这里:Interface vs Base class

这是因为您已将列表声明为 List<Entity>,但您正试图将其用作 List<EntityObject>

我认为在你的情况下你应该将你的列表声明为 List

另一种方法是像这样将您的元素转换为 EntityObject:

((EntityObject )entityList[i]).position = Vector2.One;

你采取什么方式取决于你的商业模式、你的偏好、语义和你的建议。在这种情况下,问题是:

  • 为什么你把你的列表定义成List<Entity>,然后你管理成List<Entitybject>

我同意 Facundo La Rocca(下),在访问其属性之前,您必须将对象转换为您想要使用的类型。但是,如果您要添加多个不同的实体类型(对象、字符等),那么您仍然可以将其保留为实体的基本列表。您只需要确保对于列表中的每种不同类型的实体,您检查(并转换)它是哪一个:

public static void Main(string[] args){
    var entityList = new List<Entity>();
    entityList.Add(new EntityObject()); 

    for(int i = 0; i < entityList.Count; i++) {
        if(entityList[i] is EntityObject)
            ((EntityObject)entityList[i]).position = Vector2.One;
        else if (entityList[i] is EntityCharacter)
            ((EntityCharacter)entityList[i].characterProperty = someValueToSet;
    }