Ответ Джона, конечно, правильный. Чтобы добавить немного больше деталей: принцип дизайна здесь заключается в том, что «более конкретный» метод лучше. Если у вас было:
void M(object x){}
void M(Animal x){}
void M(Giraffe x){}
и вы позвонили M(new Giraffe())
, очевидно, вы бы хотели точное совпадение. Если вы назвали M(new Tiger())
, лучшим совпадением будет «Животное», потому что тигр - это разновидность животного, тигр - это разновидность объекта, а животное - точнее , чем объект. Откуда мы знаем, что животное более специфично, чем объект? Поскольку каждое животное является объектом, но не каждый объект является животным, животное должно быть более конкретным.
Если бы вы позвонили M(null)
, мы бы выбрали версию с жирафом. Жираф более специфичен, чем Животное, потому что каждый жираф - это животное, но не каждое животное - это жираф.
В вашем примере, float лучше, чем double, потому что он более конкретен. Каждый float может быть преобразован в double, но не каждый double может быть преобразован в float, поэтому float более конкретен. Подобно тому, как каждое животное может быть преобразовано в объект, но не каждый объект может быть преобразовано в животное, так и животное более конкретно.