Подтвердить что ты не робот

Передача по значению vs Передача по эталонной производительности С#.net

Я в основном создаю легкий класс, он передается примерно с 10 параметрами, он не изменяет эти параметры, он просто сохраняет их локально, когда в конструкторе.

Некоторые типы ссылок (строки, классы), другие - типы значений (int, bool, enums).

Мой вопрос в том, должен ли я передать все это (кроме моих классов) с ключевым словом 'ref'?

Мое соображение здесь - производительность.

4b9b3361

Ответ 1

Используйте только ref, если метод должен изменить параметры, и эти изменения необходимо передать в вызывающий код. Вы должны только оптимизировать это, если вы запустили его через профилировщик и определили, что узким местом является CLR, копирующая параметры метода в стек.

Помните, что CLR сильно оптимизирован для вызова методов с параметрами, поэтому я не должен думать, что это будет проблемой.

Ответ 2

Нет. Для ссылочных типов вы уже передаете ссылку, нет необходимости передавать ссылку по ссылке, если вы не хотите изменить то, на что ссылаются контрольные точки, например. присвойте ему новый объект. Для типов значений вы можете передавать по ссылке, но если у вас нет проблемы с производительностью, я бы этого не сделал. Особенно, если типы, о которых идет речь, являются небольшими (4 байта или меньше), мало или вообще нет выигрыша в производительности, возможно даже штрафа.

Ответ 3

Если класс содержит только параметры, возможно, вы должны использовать struct?

Возможно, это представляет интерес?

Когда использовать struct?

Ответ 4

Нет. Передача параметров по ссылке добавляет служебные данные, поэтому это снизит производительность.

Ответ 5

Я обнаружил, что вызовы с большими объемами функций для более крупных типов значений, проходящие по ref, были быстрее, немного. Если у вас большой объем вызовов функций и требуется скорость, это может быть предметом рассмотрения. Я открыт для альтернативных доказательств.

public static void PassValue(decimal value)
{

}

public static void PassRef(ref decimal value)
{

}            

decimal passMe = 0.00010209230982047828903749827394729385792342352345m;

for (int x = 0; x < 20; x++)
{
    DateTime start = DateTime.UtcNow;
    TimeSpan taken = new TimeSpan();

    for (int i = 0; i < 50000000; i++)
    {
        PassValue(passMe);
    }

    taken = (DateTime.UtcNow - start);
    Console.WriteLine("Value : " + taken.TotalMilliseconds);

    start = DateTime.UtcNow;

    for (int i = 0; i < 50000000; i++)
    {
        PassRef(ref passMe);
    }

    taken = (DateTime.UtcNow - start);
    Console.WriteLine("Ref : " + taken.TotalMilliseconds);
}

Результаты:

Value : 150
Ref : 140
Value : 150
Ref : 143
Value : 151
Ref : 143
Value : 152
Ref : 144
Value : 152
Ref : 143
Value : 154
Ref : 144
Value : 152
Ref : 143
Value : 154
Ref : 143
Value : 157
Ref : 143
Value : 153
Ref : 144
Value : 154
Ref : 147
Value : 153
Ref : 144
Value : 153
Ref : 144
Value : 153
Ref : 146
Value : 152
Ref : 144
Value : 153
Ref : 143
Value : 153
Ref : 143
Value : 153
Ref : 144
Value : 153
Ref : 144
Value : 152
Ref : 143

Ответ 6

Насколько я понимаю, у вас есть класс с только полями и конструктором, который назначает параметры этим полям, правильно?

Если это так, я бы подумал об использовании ref в плохой практике конструктора. Если вы присвоите параметр полю в этом классе, он будет сохранен по значению в любом случае. Поэтому, если вы не изменяете значение в конструкторе, нет необходимости использовать его по ссылке.

Ответ 7

Я не уверен в С#, однако для С++/c это зависит от того, что вы проходите. Если вы передаете базовый тип (int, float, double, char)... тогда передача по значению быстрее, чем передача по ссылке (поскольку для этого оптимизирован вызов функции. Если вы передаете что-то большее, большой класс, массив, длинную строку... то передача по ссылке намного, намного быстрее, потому что если вы делаете int [100000], то процессор должен будет выделить 100000 x 32/64 (в зависимости от архитектуры), а затем скопируйте все значения, которые занимают много времени. В то время как по ссылке просто проходит указатель

С# абстрагирует большую часть этого, поэтому я не знаю, что он делает, но я думаю, что то, что применимо к С++/c с точки зрения эффективности, может обычно применяться к С#.