Почему это работает? Я не жалуюсь, просто хочу знать.
void Test()
{
int a = 1;
int b = 2;
What<int>(a, b);
// Why does this next line work?
What(a, b);
}
void What<T>(T a, T b)
{
}
Если вам интересно, как это работает в C # 3.0, вот небольшое видео, в котором я объяснял это еще в 2006 году, когда мы впервые разрабатывали версию этой функции для C # 3.0.
http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx
См. Также раздел «Вывод типа» в мой блог:
http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx
Компилятор достаточно умен, чтобы определить, что общий тип - это 'int'
Компилятор C# поддерживает вывод типов для generics, а также часто встречается при использовании ключевого слова var.
Здесь int
выводится из контекста (a
и b
), поэтому
не нужен. Это делает код чище и легче для чтения.
Иногда ваш код может быть более понятным для чтения, если вы позволите компилятору вывести тип, иногда он может быть более понятным, если вы явно укажете тип. Это зависит от конкретной ситуации.
Компилятор выводит общий тип параметра из типов фактических параметров, которые вы передали.
Эта возможность значительно упрощает вызовы LINQ. (Вам не нужно писать numbers.Select
, потому что компилятор выводит int
из numbers
и string
из ToString
)
Компилятор может определить тип T как int, поскольку оба параметра, переданные в What (), имеют тип int. Вы заметите, что многие расширения Linq определены с помощью универсальных шаблонов (как IEnumerable), но обычно используются так, как вы показываете.
Он использует вывод типа для общих методов. Обратите внимание, что это изменилось между C # 2 и 3. Например, это не сработало бы в C # 2:
What("hello", new object());
... тогда как в C # 3 (или 4). В C # 2 вывод типа выполнялся для каждого аргумента, и результаты должны были точно совпадать. В C # 3 каждый аргумент предоставляет информацию, которая затем объединяется для вывода аргументов типа. C # 3 также поддерживает многофазный вывод типа, когда компилятор может определить один аргумент типа, а затем посмотреть, есть ли у него дополнительная информация по остальным (например,из-за лямбда-выражений с неявными типами параметров). По сути, он продолжает работать до тех пор, пока не сможет получить больше информации, или не закончит, или пока не увидит противоречивую информацию. Вывод типа в C # не такой мощный, как алгоритм Хиндли-Милнера , но он работает лучше в других отношениях (в частности, он всегда способствует прогрессу).
См. Раздел 7.4.2 спецификации C # 3 для получения дополнительной информации.
Это работает, потому что a
и b
являются целыми числами, поэтому компилятор может вывести аргумент универсального типа для What
.
В C # 3 компилятор также может вывести аргумент типа, даже если типы не совпадают, при условии, что расширяющее преобразование имеет смысл. Например, если c
было long
, то What (a, c)
интерпретировалось бы как What
.
Обратите внимание: если, скажем, c
было строкой
, это не сработало бы.