С#/.NET имеет параметры вариационной функции, передавая по типу Array
тип-ссылку (в отличие от C/С++, который просто помещает все значения непосредственно в стек, для лучшего и худшего).
В мире С# у этого есть опрятное преимущество, позволяющее вам вызывать одну и ту же функцию с "необработанными" аргументами или экземпляром массива многократного использования:
CultureInfo c = CultureInfo.InvariantCulture;
String formatted0 = String.Format( c, "{0} {1} {2}", 1, 2, 3 );
Int32 third = 3;
String formatted0 = String.Format( c, "{0} {1} {2}", 1, 2, third );
Object[] values = new Object[] { 1, 2, 3 };
String formatted1 = String.Format( c, "{0} {1} {2}", values );
Это означает, что сгенерированный CIL эквивалентен:
String formatted0 = String.Format( c, "{0} {1} {2}", new Object[] { 1, 2, 3 } );
Int32 third = 3;
String formatted0 = String.Format( c, "{0} {1} {2}", new Object[] { 1, 2, third } );
Object[] values = new Object[] { 1, 2, 3 };
String formatted1 = String.Format( c, "{0} {1} {2}", values );
Это означает, что (в неуправляющем компиляторе JIT) каждый вызов будет выделять новый Object[]
экземпляр, хотя в третьем примере вы можете сохранить массив как поле или другое значение многократного использования, чтобы исключить новое распределение при каждом вызове String.Format
.
Но в официальной среде CLR и JIT есть какие-либо оптимизации для устранения этого распределения? Или, может быть, массив помечен специально, чтобы он был освобожден, как только выполнение оставит область вызова сайта?
Или, может быть, потому, что компилятор С# или JIT знает количество аргументов (при использовании "raw" ), он мог бы сделать то же самое, что и ключевое слово stackalloc
, и поместить массив в стек, и, следовательно, не нужно освободить его?