Когда компилятор видит, что вызывается метод, который принимает больше параметров, чем ему передается, то он идет в метаданные модуля и смотрит, являются ли оставшиеся параметры опциональными
Далее Рихтер пишет, что у этих параметров также есть атрибут DefaultParameterValue, в котором хранится значение по умолчанию и компилятор берет это значение и подставляет в вызывающий код, на в dotpeek я такой атрибут не нашел, тем не менее компилятор может проверить является ли этот атрибут опциональным и, если является, взять его значение из метаданных, кстати в IL коде метода с опциональными параметрами, также записываются default значения
В итоге в IL коде происходит вызов со всеми заполненными параметрами:
Компилятор, когда встречает метод с недостающими параметрами, проверяет является ли они опциональными, если да - ищет их в методанных и явно проставляет в IL коде А вызов сам происходит как обычно
Какой IL код генерируется при вызове метода и передаче именованных параметров и каким образом он генерируется
Такой же как и при обычном вызове метода, поскольку вся работа по определению параметров ложится на компилятор, он смотрит в метаданные модуля, находит параметр с таким же именем у этого метода и понимает в каком порядке их нужно заталкивать в стек
Копируются, если это value type - то копируется значения, если reference type - указатель
При использовании ключевого слова ref - компилятор ожидает, что параметр будет проинициализирован перед тем как отправлен в метод, out - что параметр будет проинициализирован уже внутри метода
Только если программист хочет чтобы указатель стал "указывать" на другой объект в памяти, т.к, если не использовать ref или out в метод передается копия указателя, по которой можно мутировать объект, но если присвоить этому указателю ссылку на другой объект, то смысла в этом не будет, т.к указатель из вызывающего метода останется таким же, поэтому если программист хочет явно отвязать указатель от одного объекта к другому, то ему нужно использовать ref
В обоих случаях параметр помеченный, как ref или out передается либо значения(value type), либо указатель на указатель объекта в куче(reference type)
public void One(int t)
{
}
public void One(ref int t)
{
}
А вот такие два нельзя:
public void One(ref int t)
{
}
public void One(out int t)
{
}
В первом случае, потому что IL код полученных методов отличается, вот таким образом:
В верхнем методе передается значение переменной, а перед типом стоит & - указывающий, что идет работа с адресом в памяти этого объекта, а не с его значением
Во втором случае в IL получаются методы с одинаковыми сигнатурами, потому что для CLR все-равно какое ключевое слово используется, потому что сделать нужно одно и тоже, передать указатель на переменную в стеке, это может быть как значение - value type, так и указатель - reference type, разницу между словами ref и out остлеживает только компилятор
Потому что возможны вот такие конфузы(если бы этот код компилировался)
Т.e можно бы было поменять тип объекта, поэтому в методы с параметрами ref и out нужно посылать максимально точный тип