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;
}
首先,我创建基础 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;
}