На днях Microsoft анонсировала новую версию C#. В ней есть фича, касающаяся
params. Если вы не в курсе, что это такое, то вот простой пример:public void SomeMethod() {
ArrayParams(1);
ArrayParams(1, 2, 3);
}
public void ArrayParams(params int[] values) {
// some work
}Ключевое слово
params – это синтаксический сахар, позволяющий вызывать метод ArrayParams с любым количеством параметров. Но за сахар надо платить, в данном случае – ненужными аллокациями. После компиляции в методе SomeMethod на каждый вызов ArrayParams создаётся экземпляр массива int[].public void SomeMethod() {
int[] array = new int[1]; // аллокация 1
array[0] = 1;
ArrayParams(array);
int[] array2 = new int[3]; // аллокация 2
RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
ArrayParams(array2);
}Но в новой версии C# можно использовать
Span<T> и ReadOnlySpan<T> вместо массива.public void SomeMethod() {
SpanParams(1);
SpanParams(1, 2, 3);
}
public void SpanParams(params ReadOnlySpan<int> values) {
// some work
}В итоге, в теле метода
SomeMethod аллокаций уже не будет. То есть, если вы любите писать высокопроизводительный код, то params вместе с ReadOnlySpan<T> — ваш бро.public void SomeMethod() {
SpanParams(RuntimeHelpers.CreateSpan<int>((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/));
SpanParams(RuntimeHelpers.CreateSpan<int>((RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/));
}Но также стоит учесть, что использование
Span<T> накладывает ограничения – метод нельзя сделать асинхронным.// valid
public async Task ArrayParams(params int[] values) {
// some work
}
// error CS4012: Parameters or locals of type 'ReadOnlySpan<int>'
// cannot be declared in async methods or async lambda expressions.
public async Task SpanParams(params ReadOnlySpan<int> values) {
// some work
}