将派生对象存储到其基类型的集合中——为啥它会起作用?
Posted
技术标签:
【中文标题】将派生对象存储到其基类型的集合中——为啥它会起作用?【英文标题】:Storing derived objects to a collection of its base type--why does it work?将派生对象存储到其基类型的集合中——为什么它会起作用? 【发布时间】:2018-04-02 21:59:10 【问题描述】:我创建了一个被视为地图的 20x20 多维数组。
private LinkedList<Item>[,] m_map = new LinkedList<Item>[width, height];
每个单元格都是一个Item类型的链表。武器、盔甲等物品可以放入每个单元格中。
我有以下类层次结构:
class Item
public string name;
class Weapon : Item
public int damage;
class Armor : Item
public int ar;
public int weight;
我有点惊讶,并希望接受这方面的教育。由于类型是 LinkedList
/// <summary>
/// Gets a list of weapons at the given coordinates.
/// </summary>
/// <param name="x">The map's horizontal position.</param>
/// <param name="y">The map's vertical position.</param>
/// <returns>Returns a list of weapons at the given coordinates.</returns>
public List<Weapon> GetWeapons(int x, int y)
List<Weapon> weapons = new List<Weapon>();
foreach (Item item in m_map[x, y])
if (item is Weapon)
weapons.Add(item as Weapon);
return weapons;
Item 包含的字段比 Armor 少,所以我认为 LinkedList
当您将派生类型及其基类型存储到链接列表时,编译器是否为其派生类型腾出足够的内存?我很惊讶我可以检索 Armor 类型并仍然获得其派生数据(ar,重量)。
有人能解释一下为什么会这样吗?谢谢。
【问题讨论】:
它存储references,如果你熟悉像C这样的语言,它们本质上是指针。这是使多态起作用的唯一方法。所有对象引用的大小相同。 哦,我明白了。所以集合存储引用而不是二进制副本。 参考类型。对于值类型,它存储一个副本。另见:***.com/questions/14669651/… 【参考方案1】:正如 Cody Gray 在他的评论中所写,LinkedList 存储的是引用,而不是值。
对引用的简单解释是,它是内存中实际值所在位置的地址。 由于您只存储引用,因此包含 100 件物品的列表所消耗的内存量与包含 100 件武器或盔甲的列表所消耗的内存量相同。
但是,这只是您可以将派生类实例存储在父类列表中的部分原因 - 另一部分是称为多态性的基本 OOP 概念 - Armor
或 Weapon
是实际上是Item
的一种类型,使您可以将它们中的每一个存储在任何类型为Item
的强类型集合中,因为您可以使用Item
类型的引用来指向一个实例Armor
或 Weapon
。
回答您对 Cody 的评论 - 不。集合存储您决定存储的任何内容。例如,如果您要声明int
的列表,它将存储实际值,因为int
是一个值类型。
您可能想了解value types 与reference types。
主要区别在于值类型变量直接包含值, 而引用类型变量包含一个指向实际值存储位置的“指针”。
【讨论】:
我了解引用和值类型。我不明白的是,如果一个 Item 类型包含 2 个字段(比如两个整数),那就是 64 个字节的空间。如果它指向可能有 4 个整数(128 字节)的 Armor 类型,则 Item 指向一个比它自己大的对象,但它仍然能够检索其数据。我想了解它是如何做到的。 * 对不起,清晨:8字节,16字节。 你问这个问题意味着你不明白什么是引用。引用的大小始终相同,因为它不是实际数据,几乎是指向存储数据的地址的指针。这意味着对包含 100 个 Int64 值成员的类实例的引用与对包含单个 Int16 成员的类实例的引用大小完全相同。以上是关于将派生对象存储到其基类型的集合中——为啥它会起作用?的主要内容,如果未能解决你的问题,请参考以下文章