将派生对象存储到其基类型的集合中 - 为什么它可以工作?

时间:2017-10-22 05:58:21

标签: c#

我创建了一个被视为地图的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&lt;项目&gt;,我认为我不能存储Armor类型并检索它。这就是我检索特定项目类型的方式:

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

项目包含的字段少于Armor,因此我认为类型为LinkedList&lt;项目&gt;会比Armor小。但是,似乎有足够的空间来保存Armor对象。我能够检索Armor的数据。

当您将派生类型存储到具有基类型的链接列表时,编译器是否为其派生类型创建了足够的内存?我很惊讶我可以检索一个Armor类型并仍然得到它的派生数据(ar,weight)。

有人可以解释为什么会这样吗?谢谢。

1 个答案:

答案 0 :(得分:1)

正如Cody Gray在评论中写道,LinkedList存储引用,而不是值。

参考的简化说明是它是存储器中实际值所在位置的地址。
由于您只存储引用,因此100个项目的列表仅消耗与100个武器或装甲列表相同的内存量。

然而,这只是您可以将派生类实例存储在父类列表中的部分原因 - 另一部分是称为多态的基本OOP概念 - Armor或{Weapon {1}} 实际上是一种Item类型,您可以将它们存储在任何类型为Item的类型集合中,因为您可以使用类型的引用Item指向ArmorWeapon的实例。

回答您对Cody的评论 - 不会。收藏品会存储您决定存储的内容。例如,如果您在哪里声明int列表,它将存储实际值,因为int是值类型。

您可能希望阅读value types vs reference types

主要区别在于值类型变量直接包含值, 而引用类型变量包含一个&#34;指针&#34;到存储实际值的位置。