Допустимо ли возвращать порядковый номер объекта в GetHashCode()?
Универсальное правило переопределения хеш кода от Joshua BlochStore some constant nonzero value, say 17, in an int variable called result.
    Compute an int hashcode c for each field f that defines equals:If the field is a boolean, compute (f ? 1 : 0)        If the field is a byte, char, short, int, compute (int) f        If the field is a long, compute (int) (f ^ (f >>> 32))        If the field is a float, compute Float.floatToIntBits(f)        If the field is a double, compute Double.doubleToLongBits(f), then hash the resulting long as in above.        If the field is an object reference and this class's equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If the value of the field is null, return 0.        If the field is an array, treat it as if each element is a separate field. If every element in an array field is significant, you can use one of the Arrays.hashCode methods added in release 1.5.    Combine the hashcode c into result as follows: result = 31 * result + c;
Использовать только id - нормально, но его нужно умножать на некоторое число.
Методы GetHashCode и Equals нужно переопределять, если вы хотите, чтобы два различных экземпляра одного класса могли считаться одинаковыми. В вашем же случае экземпляр будет равен только самому себе, потому что Id всегда будут уникальными. Получается, вы переизобрели семантику сравнения по ссылке, которая и так работает по умолчанию, если не переопределять GetHashCode и Equals вообще.
Еще одна проблема возникнет, если вы будете использовать этот код в многопоточном окружении - без синхронизации доступа к LastLeasedID рано или поздно получите дубликаты.