почему-то нельзя использовать ref и params одновременно. Почему так?
Рассмотрим эти три желательные характеристики камер:
легкий
высококачественный объектив
недороги
Вы можете получить не более двух из них в любой камере. Вы никогда не получите все три. Вы можете приобрести недорогие тяжелые камеры с большим объективом, дорогие легкие камеры с большим объективом или недорогие легкие камеры с моментальными снимками, но недорогих легких камер с большими объективами не существует.
Возвращаясь теперь к вашему вопросу. Рассмотрим эти три желательные характеристики среды выполнения:
допустимы массивы параметров типов ref-to-variable
система типа безопасна
локальные переменные, имеющие ссылки на них, по-прежнему быстро распределяются и освобождаются
Вы можете иметь любые два, но вы не можете иметь все три. Какие два вы бы хотели?
Вы можете иметь массивы ref param и систему безопасных типов за счет того, что локальные переменные ref'd распределяются в куче мусора. Насколько мне известно, никто не делает этого, но это, безусловно, возможно.
Вы можете иметь массивы ref param, все локальные переменные, выделенные во временном пуле, и систему типов, которая вылетает при неправильном использовании. Это подход "C / C ++"; можно взять ссылку и сохранить ее в месте, которое имеет более длительный срок службы, чем срок действия объекта, на который делается ссылка. Если вы сделаете это, вы можете ожидать, что ваша программа на C ++ потерпит крах и погибнет самым ужасным из возможных способов, совершив простые ошибки, которые трудно обнаружить. Добро пожаловать в пропасть отчаяния.
Или мы можем сделать массивы ref param недопустимыми, распределить все локальные переменные во временном пуле и создать систему типов, надежно защищенную от памяти. Это выбор, который мы сделали при сборке C # и CLR; добро пожаловать в яму качества.
Теперь, то, что я сказал выше, на самом деле - большая ложь. Это ложь, потому что среда выполнения и язык C # на самом деле do поддерживают функцию, похожую (но не идентичную) на массивы параметров refs. Это приятная ложь и поверь мне, ты хочешь жить в мире, где ты веришь лжи , поэтому я рекомендую тебе принять синюю таблетку и продолжать делать это.
Если вы хотите взять красную таблетку и выяснить, насколько глубоко заходит кроличья нора, вы можете использовать недокументированную функцию __arglist
в C # для создания метода вариации C-стиля , а затем сделать TypedReference
объекты, которые ссылаются на ссылки произвольных полей или локальных объектов структурных типов, а затем произвольно передают многие из них в метод variadic. Используйте фабричные методы TypedReference
или недокументированную функцию __makeref
в C #.
Причина, по которой мы сохранили эти функции недокументированными в течение последнего десятилетия, заключается в том, что они предназначены для использования там только для крайне редких ситуаций, когда вы должны писать код C #, который корректно взаимодействует с методами с переменным числом написанных на других языках.
Правильное использование TypedReference
объектов не для слабонервных, и снова я настоятельно рекомендую не делать этого. Я никогда не делал этого в производственном коде за много лет написания C #. Если вы хотите передать ссылки на сколь угодно много переменных, передайте массив . Массив по определению является набором переменных. Это гораздо безопаснее, чем передавать кучу объектов, представляющих управляемые адреса экземпляра или локальные переменные.