2017-01-09 151 views
1

首先,我创建基类和继承类C#访问继承了基类的列表类的属性

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

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

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

后来,我尝试访问列表中的继承类的成员

for(int i = 0; i < entityList.Count; i++) 
    if(entityList[i].type == EntityType.OBJECT) 
     entityList[i].position = Vector2.One; 

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

是否有可能访问从基类列表继承类属性?

+0

一个单独的考虑是你比较重量级'List'类时的使用你只需要一个'IEnumerable'实现。 –

回答

2

您需要的Entity实例强制转换为EntityObject情况下,因为Position场的确不是Entity

所以部分:

var entityObjectInEntityList = (EntityObject)entityList[0] 

会给你正确的类型,你可以再访问.Position字段反对。


正如在评论中提到,你也可以测试类型/做演员以下几种方式:

if(entityList[0] is EntityObject) 

只是测试类型 - 通常避免,因为你仍然需要投得到正确的类型和涉及的开销

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

OR用C#6

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

使用as关键字进行铸造,如果失败,则返回一个空。


在慈悲的利益,由亨克指出的那样,你想清楚,包括你的类中的一些类型的信息,在EntityType财产的形式。

可以决定一个对象在运行时的类型:

var type = instance.GetType(); 

因此:

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

会告诉你该实例的类型,但是使用像派生类的类型检查往往是一种气味。

假设您不需要任何基本功能Entity我建议使用接口方法。

我建议你看这里:Interface vs Base class

+1

加油,也取代DIY型系统。 –

+5

比明确的强制转换更好,将使用'as'关键字和空检查相结合。请参阅http://stackoverflow.com/questions/496096/casting-vs-using-the-as-keyword-in-the-clr –

+1

是的,我也没有考虑过GetType()。 “is”和“as”存在几种解决方案。 –

0

这是因为你声明的列表为List<Entity>,但你要使用它作为List<EntityObject>

我认为你的情况你应该声明你的列表为列表< EntityObject>。

的另一种方式是投你的元素EntityObject是这样的:

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

什么方式,你需要取决于你的经营业务模式,您的喜好,语义和你的建议。在这种情况下,问题是:

  • 你为什么要定义名单为List<Entity>,然后你管理它List<Entitybject>
+0

因为有各种继承的类存储在列表中,这就是为什么我声明为列表 vertiria

+0

完美的,在这种情况下,你必须施放它们。但你可能想要更明确地分解方法。 –

0

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

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