Невероятно, но я разгадал в чём проблема.
Проблема кроется в том, что вы используете класс Array
public static Array Values { get => ValuesArray; }
Когда вы используете Array внутри foreach, то с ним происходит работа как с System.Collections.IEnumerable (не Generic).
Тоесть каст будет происходить не DirEnum->Dir, а Object->Dir
Как доказательство, вот кусочек IL:
IL_000e: callvirt instance object [System.Runtime]System.Collections.IEnumerator::get_Current()
IL_0013: castclass Dir
Более упрощённо можно повторить эту проблему, если сделать так:
DirEnum a = DirEnum.Up;
object box = x;
Dir y = (Dir) box; // Казалось бы, у нас есть оператор DirEnum->Dir, но вызываться будет castClass, а не переопределённый оператор
Если заменить Array на
IReadOnlyCollection<DirEnum>
, то всё будет ок.
Ну или если вместо Dir в foreach взять DirEnum
PS:
Суффиксы Enum и Array у имён нужны. Лучше бы назавали DirEnum - Direction, Dir - DirectionBox, а ValuesArray - allValues, это кстати тоже не нужно, тк есть метод Enum.GetValues