Потому что они тесно связаны. Например Dictionary строить хеш-таблицу на основе HashCode и ищет объекты в ней по нему же, потому что это быстро и нужно сравнивать только одно число. А после того как найдёт подходящие объекты, сравнивает с искомым уже через Equals, чтобы наверняка убедиться, что это он.
А для пользовательских классов GetHashCode будет возвращать "рандомный мусор" (на самом деле там что-то завязано на расположение объекта в памяти), соответственно идентичные по содержимому объекты будет иметь разные HashCode, что негативно сказывается на некоторых механизмах.