Упакованный Int32 тоже реализует интерфейс IComparable, но поскольку упакованный Int32 был приведен к типу Object, необходим явный каст к интерфейсному типу.
Создается объект на куче, значение int копируется в поле этого нового объекта, а сам объект приводится к типу object, который не реализует интерфейс IComparable
Да, но int не перестает быть int-том если на него указывает ссылка с типом object.
В данном случаи obj это ссылка с типом object, которая указывает на упакованый int. Когда вы приводете ее(ссылку) к IComparable, то ранатйм смотрит на то место куда она указывает, а там лежит int который знает что такое IComparable.
Рекомендую почитать про наследование и адресацию в памяти.
Это позволяет уменьшить количество глупых логических ошибок при преобразованиях, вся ответвеность за "страные" преобразования ложиться на плечи програмиста.
Когда вы пишите "number." в последней строчке система понятия не имеет, что obj содержит интовое значение и просто показывает методы для интерфейса IComparable.
Но это вовсе не значит, что код будет работать )