Ответ 1
Вызывается строка int bar, потому что 10
является int literal, и компилятор будет искать метод, который ближе всего соответствует входной переменной (ей). Чтобы вызвать длинную версию, вам нужно указать длинный литерал следующим образом: foo.bar(10L);
Вот сообщение Эрика Липперта о гораздо более сложных версиях перегрузки методов. Я бы попытался объяснить это, но он делает гораздо лучшую работу, и я мог: http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
из спецификации С# 4.0:
Перегрузка метода допускает множественное методы в том же классе, чтобы иметь одно и то же имя, если у них есть уникальные подписи. При компиляции вызов перегруженного метода, компилятор использует разрешение перегрузки для определения конкретного метода вызов. Разрешение перегрузки обнаруживает один метод, который наилучшим образом соответствует аргументы или сообщения об ошибке, если нет можно найти единственное лучшее совпадение. следующий пример показывает перегрузку разрешение. Комментарий для каждый вызов в основном методе показывает, какой метод на самом деле вызывается.
class Test {
static void F() {
Console.WriteLine("F()");
}
static void F(object x) {
Console.WriteLine("F(object)");
}
static void F(int x) {
Console.WriteLine("F(int)");
}
static void F(double x) {
Console.WriteLine("F(double)");
}
static void F<T>(T x) {
Console.WriteLine("F<T>(T)");
}
static void F(double x, double y) {
Console.WriteLine("F(double,double)");
}
static void Main() {
F(); // Invokes F()
F(1); // Invokes F(int)
F(1.0); // Invokes F(double)
F("abc"); // Invokes F(object)
F((double)1); // Invokes F(double)
F((object)1); // Invokes F(object)
F<int>(1); // Invokes F<T>(T)
F(1, 1); // Invokes F(double, double)
}
}
Как показано на примере, конкретный метод всегда можно выбрать явно отбрасывая аргументы точные типы параметров и/или явно передавая аргументы типа.