It's dangerous to code alone! Take this.

Labeling Inventory

The following is one possible solution to this challenge.

Pack pack = new Pack(10, 20, 30);

while (true)
{
    Console.WriteLine(pack);
    Console.WriteLine($"Pack is currently at {pack.CurrentCount}/{pack.MaxCount} items, {pack.CurrentWeight}/{pack.MaxWeight} weight, and {pack.CurrentVolume}/{pack.MaxVolume} volume.");

    Console.WriteLine("What do you want to add?");
    Console.WriteLine("1 - Arrow");
    Console.WriteLine("2 - Bow");
    Console.WriteLine("3 - Rope");
    Console.WriteLine("4 - Water");
    Console.WriteLine("5 - Food");
    Console.WriteLine("6 - Sword");
    int choice = Convert.ToInt32(Console.ReadLine());

    InventoryItem newItem = choice switch
    {
        1 => new Arrow(),
        2 => new Bow(),
        3 => new Rope(),
        4 => new Water(),
        5 => new Food(),
        6 => new Sword()
    };

    if (!pack.Add(newItem))
        Console.WriteLine("Could not add this to the pack.");
}

public class Pack
{
    public int MaxCount { get; }
    public float MaxVolume { get; }
    public float MaxWeight { get; }

    private InventoryItem[] _items;

    public int CurrentCount { get; private set; }
    public float CurrentVolume { get; private set; }
    public float CurrentWeight { get; private set; }

    public Pack(int maxCount, float maxVolume, float maxWeight)
    {
        MaxCount = maxCount;
        MaxVolume = maxVolume;
        MaxWeight = maxWeight;

        _items = new InventoryItem[maxCount];
    }

    public bool Add(InventoryItem item)
    {
        if (CurrentCount >= MaxCount) return false;
        if (CurrentVolume + item.Volume > MaxVolume) return false;
        if (CurrentWeight + item.Weight > MaxWeight) return false;

        _items[CurrentCount] = item;
        CurrentCount++;
        CurrentVolume += item.Volume;
        CurrentWeight += item.Weight;
        return true;
    }

    public override string ToString()
    {
        string contents = "Pack containing ";
        if (CurrentCount == 0) contents += "Nothing";

        for (int itemNumber = 0; itemNumber < CurrentCount; itemNumber++)
            contents += _items[itemNumber].ToString() + " ";

        return contents;
    }
}

public class InventoryItem
{
    public float Weight { get; }
    public float Volume { get; }

    public InventoryItem(float weight, float volume)
    {
        Weight = weight;
        Volume = volume;
    }
}

public class Arrow : InventoryItem
{
    public Arrow() : base(0.1f, 0.05f) { }

    public override string ToString() => "Arrow";
}

public class Bow : InventoryItem
{
    public Bow() : base(1, 4) { }

    public override string ToString() => "Bow";
}

public class Rope : InventoryItem
{
    public Rope() : base(1, 1.5f) { }

    public override string ToString() => "Rope";
}

public class Water : InventoryItem
{
    public Water() : base(2, 3) { }

    public override string ToString() => "Water";
}

public class Food : InventoryItem
{
    public Food() : base(1, 0.5f) { }

    public override string ToString() => "Food";
}

public class Sword : InventoryItem
{
    public Sword() : base(5, 3) { }

    public override string ToString() => "Sword";
}

// Answer this question: We could have made a different method or property (for example
// `Description`) instead of overriding `ToString`. Which do you prefer and why?
//
// This is a very opinion-based question, and there isn't a right answer. I've done
// both in different circumstances. One catch with `ToString` is that it is used all
// over the place. If there isn't a single, definitive string representation for something,
// it might be better to make another property instead. But as I said, it is used
// all over the place. If you override `ToString`, then you can do something as simple
// as `Console.WriteLine(new Sword());` and it will display that text. If you made a
// `Description` property, you wouldn't get that benefit. You'd have to do
// `Console.WriteLine(new Sword().Description);` instead.
//
// For this particular challenge, I like overriding `ToString`. It keeps the code the
// simplest. It doesn't demand making a whole other property. But had the code been more
// complicated, and had there been a need for multiple text representations of the item
// (say, a title and a description) then I might have chosen to make `Title` and
// `Description` properties instead.