Я сомневаюсь, что вы обнаружите значительное снижение производительности при использовании параметра out
. Вы должны так или иначе вернуть информацию вызывающему абоненту - out
- это просто другой способ сделать это. Вы можете столкнуться с некоторыми штрафами, если будете широко использовать параметр out внутри метода, так как это может означать дополнительный уровень перенаправления для каждого доступа. Тем не менее, я бы не ожидал, что это будет значительным. Как обычно, напишите максимально читаемый код и проверьте, достаточно ли хороша производительность, прежде чем пытаться оптимизировать дальше.
РЕДАКТИРОВАТЬ: Остальное в стороне, эффективно. Это действительно актуально только для больших типов значений, которых в любом случае следует избегать:)
Я не согласен с утверждением Конрада о том, что «возвращаемые значения для всех типов> 32 бит в любом случае обрабатываются аналогично или идентичным аргументам out на машинном уровне». Вот небольшое тестовое приложение:
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
struct BigStruct
{
public Guid guid1, guid2, guid3, guid4;
public decimal dec1, dec2, dec3, dec4;
}
class Test
{
const int Iterations = 100000000;
static void Main()
{
decimal total = 0m;
// JIT first
ReturnValue();
BigStruct tmp;
OutParameter(out tmp);
Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
BigStruct bs = ReturnValue();
total += bs.dec1;
}
sw.Stop();
Console.WriteLine("Using return value: {0}",
sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
BigStruct bs;
OutParameter(out bs);
total += bs.dec1;
}
Console.WriteLine("Using out parameter: {0}",
sw.ElapsedMilliseconds);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static BigStruct ReturnValue()
{
return new BigStruct();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void OutParameter(out BigStruct x)
{
x = new BigStruct();
}
}
Результаты:
Using return value: 11316
Using out parameter: 7461
По сути, используя выходной параметр, мы записываем данные непосредственно в конечный пункт назначения, а не записываем их в фрейм стека малого метода, а затем копируем их обратно в фрейм стека метода Main.
Не стесняйтесь критиковать тестовое приложение — возможно, я что-то упустил!
person
Jon Skeet
schedule
09.02.2009