Can't access methods from class

So I have this script with two classes:
using UnityEngine;
using System.Collections;

public class GameItem {

	public string ItemName { get; set; }

	public string ItemDesc { get; set; }

	public Item_Type ItemType { get; set; }

	public int ItemValue { get; set; }

	public int ItemID { get; set; }

	public GameItem () {

	}

	public GameItem (string name, string desc, Item_Type type, int value, int id) {
		this.ItemName = name;
		this.ItemDesc = desc;
		this.ItemType = type;
		this.ItemValue = value;
		this.ItemID = id;
	}
}

public class Weapon : GameItem {

	public string WeapEnch { get; set; }

	public float WeapEffic { get; set; }

	public Weapon () {

	}

	public Weapon (string name, string desc, string ench, float effic, int value, int id) {
        this.ItemType = Item_Type.WEAPON;
        this.ItemName = name;
        this.ItemDesc = desc;
		this.WeapEnch = ench;
		this.WeapEffic = effic;
        this.ItemValue = value;
        this.ItemID = id;
	}

    public void Attack () {
        Debug.Log("Attack tho");
    }
}

public enum Item_Type {
	APPAREL,
	WEAPON,
	TOOL,
	CONSUMABLE,
	BOOK,
	MISC
}

And then I have a script for adding items to a list using the constructors:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class InventoryManager : MonoBehaviour {

	public List<GameItem> GameItems { get; set; }

	void Start () {
        GameItems.Add(new Weapon("Sword.", "It's a sword.", null, 5.0f, 15, 0));
	}
	
	void Update () {
		if(Input.GetButtonDown("Interact")) {
            GameItems[0].Attack();  // can't do this
		}
	}
}

So when I create a new Weapon in the list, I can access everything from the GameItem class, but nothing from the Weapon class, even though I used the Weapon constructor. So I can’t use the Attack () function, or access the weapon’s variables. How can I get around this problem? Or how can I design the system to where I can use the methods and variables from all the classes that inherit from GameItem?

You can’t access anything from Weapon without a cast. The point of inheritance is to be able to treat objects in a general / generic way. So a GameItem reference might contain a Weapon but doesn’t have to. The compiler doesn’t know the type at compile time so you can’t call Attack since that method doesn’t exist in GameItem.

So solution one is to as-cast the type like this:

if(Input.GetButtonDown("Interact")) {
    Weapon wep = GameItems[0] as Weapon;
    if (wep != null)
        wep.Attack();
}

The second solution would be to use an “is” check and a normal cast:

if(Input.GetButtonDown("Interact")) {
    if (GameItems[0] is Weapon)
        ((Weapon)GameItems[0]).Attack();
}

Finally it’s also possible to declare a virtual Attack method inside the GameItem class which the Weapon class can override:

public class GameItem {
    // [ ... ]
    public virtual void Attack()
    {
        // Do nothing
    }
}

public Weapon : GameItem
{
    // [ ... ]
    public override void Attack()
    {
        Debug.Log("Attack!");
    }
}