Полагаю, вы ищете безопасность во время компиляции. Поэтому я предлагаю использовать обобщенные методы для решения этой проблемы.
Определите базовый класс для типов ваших слотов и их реализаций:
public abstract class Slot { }
public sealed class Head : Slot { }
public sealed class Torso : Slot { }
public sealed class Legs : Slot { }
Ваша реализация Armor может выглядеть примерно так:
public abstract class Armor { }
public sealed class Armor<TSlot> : Armor
where TSlot : Slot, new()
{
public TSlot Slot { get; }
public Armor() => Slot = new TSlot();
}
Соответствующим битом является то, что вы разрешаете создавать только экземпляры generi c с указанным типом слота c. Ограничение new () было добавлено только для того, чтобы мой пример кода был коротким.
Теперь вы готовы создать ограничительную и безопасную во время компиляции реализацию словаря для экземпляров Armor, используя любой слот в качестве ключа:
public sealed class SafeDictionary
{
private readonly Dictionary<Slot, Armor> _dictionary = new Dictionary<Slot, Armor>();
public Armor this[Slot slot] => _dictionary[slot];
public void Add<TSlot>(TSlot slot, Armor<TSlot> armor)
where TSlot : Slot, new()
{
_dictionary.Add(slot, armor);
}
}
Использование в зависимости от того, какие пары значений ключей вы добавляете, бесплатное:
var head = new Armor<Head>();
var torso = new Armor<Torso>();
var torsoKey = new Torso();
var dictionary = new SafeDictionary();
dictionary.Add(head.Slot, head);
dictionary.Add(torsoKey, torso);
Console.WriteLine(torso == dictionary[torsoKey]);
// Do not compile:
// dictionary.Add(torsoKey, head);
// dictionary.Add<Torso>(torsoKey, head);
Это позволяет вам использовать любое количество ключей (слотов) с любым количеством значений (броней). По вашему требованию невозможно добавить экземпляр Armor со слотом Head, используя ключ Torso. (И любая другая несовместимая комбинация). Цена, которую вы платите, это необходимость одного интерфейса маркера (слот, здесь как абстрактный класс) и в этом примере пустой реализации Armor. Если вы хотите восстановить свойство Slot в Armor, это можно сделать, добавив интерфейс IArmor. Также были бы возможности ограничить экземпляры Head, Torso и Legs синглетами, чтобы приблизиться к вашему примеру использования перечислений, но здесь это выходит за рамки.
Я надеюсь, что приведенное выше решение даст вам достаточно материала для решения вашей проблемы и разработки решения, которое наилучшим образом соответствует вашим потребностям.