2014-11-28 2 views
-3

Если у вас есть метод, который принимает переменную и фактически не изменяет физическую переменную, следует ли использоватьrefдля указания входного параметра? Это не имеет большого значения, потому что переменная не изменяется в любом случае, так что же недостатки/преимущества использования ref? (В C#, по крайней мере)Должно ли использоваться значение или ссылка, если оба работают одинаково?

Например,

int[] numbers = new int[] { /* some numbers */ }; 
int getNumberValue(int index) 
{ 
    return numbers[index]; 
} 
int getNumberRef(ref int index) 
{ 
    return numbers[index]; 
} 

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

Я бы подумал, что версия ref будет быстрее, если я использую ее в 18 миллиардов раз, поскольку версия значения, вероятно, делает клон параметра, поэтому метод может изменить его (но я могу ошибаться), хотя могут быть некоторые недостатки.

+2

'Я бы подумал, что версия ref будет быстрее: http://ericlippert.com/2012/12/17/performance-rant/ –

+0

Вы хотите нарезать хлеб. Вы можете взять нож из ящика или пойти купить катану, чтобы нарезать хлеб. Зачем вам использовать катану, если вам это явно не нужно? Используйте katana *, когда * вам нужно. (Плохая аналогия на самом деле, катаны - здоровы, и я бы использовал их, чтобы нарезать хлеб, если бы у меня был один) – dcastro

+0

@dcastro вы правы, * Плохая аналогия *. –

ответ

0

Они функционально эквивалентны, но они семантически Очень разные.

Метод с подписью, такой как Method(ref string s), указывает клиентам, что может потребоваться присвоить s новое значение. Таким образом, клиент будет действовать в соответствии с этим ложным предположением и делать то, что ему не нужно, например, если s имеет значение null после вызова вашего метода или какой-либо другой проверки.

Также, как общий совет по программированию, не используйте то, что вам не нужно! Вы добавляете излишнюю сложность, вы соблазняете себя и других. Это поведение, которое приводит к cargo cult programming.

+0

Я думал, что это будет быстрее, потому что 'ref' не нужно клонировать переменную, но нет .... Также [this] (https://dotnetfiddle.net/HaL5e9) – user1319644

+0

@ user1319644 Значение только * клонировано * если это тип значения (например, 'int',' double', 'bool'). Эти значения настолько малы, что это не имеет большого значения. Кроме того, в некоторых случаях perf может быть даже хуже: быстрее clone a boolean (1 байт), чем указатель на логический (4/8 байт) – dcastro

+0

Кроме того, [«преждевременная оптимизация - это корень всех злых»] (http://stackoverflow.com/questions/385506/when-is -оптимизация - преждевременная). Не беспокойтесь о таких мелких деталях - сосредоточьтесь на написании правильного, гибкого и поддерживаемого программного обеспечения. Если ваше приложение не меняет и ваши требования к производительности, а затем используйте профилировщик, чтобы найти узкое место - 99% времени, узкое место связано с доступом к диску, базой данных или сетевыми соединениями. Это то, о чем вам следует беспокоиться. – dcastro

0

Полезный ответ: вам почти не нужно использовать ref/out. Это в основном способ получить другое возвращаемое значение и обычно следует избегать именно потому, что это означает, что метод, вероятно, пытается сделать слишком много. Это не всегда так (TryParse и т. Д. Являются каноническими примерами разумного использования out), но использование ref/out должно быть относительной редкостью.

Дополнительная информация here.

1

Вы не используете ref так. ref действительно изменяет ссылку переданной переменной. Итак, вы используете это, когда вам это нужно. Просто как тот.

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

Ref работает следующим образом:

int a = 5; 
int b = 6; 


_swap(ref a, ref b); 


// a is now 6 and b is now 5; 

Это Своп-метод:

void _swap(ref int a, ref int b) 
{ 
    int tmp = a; 
    a = b; 
    b = tmp; 
} 

Попробуй here

+0

. Я действительно знаю, что делает 'ref', я просто задавался вопросом, есть ли веские причины использовать его, когда вам не нужно. – user1319644