2015-11-19 3 views
2

Хорошо, это может быть действительно глупый вопрос, но я буду рисковать своим представителем. Я довольно новичок в программировании, так что успокойся. Ya;) Итак, я только что попал в TCP, когда столкнулся с чем-то, чего я не совсем понял. Конкретно:Общие методы, которые перезаписывают параметры без ссылки?

int length = Socket.Receive(MyByteArray); 

В моем понимании этот метод возвращает длину данных неоспоримый получил и записывает данные в ПОЛУЧАЛИ мой массив байт. Итак, как он записывается в мой байтовый массив, не говоря мне об этом? После некоторых исследований я узнал, что вы можете использовать ссылки, чтобы делать такие вещи, но этот метод не требует «ref MyByteArray», который оставляет меня озадаченным. Это другой метод или это то, что происходит внутри метода (duh)?

Заранее благодарен вам, что вы удивительный человек.

+5

Проведите некоторое исследование ссылочных типов и типов значений. Массивы являются ссылочными типами, поэтому, когда вы передаете один из функций, он имеет _reference_ для фактического объекта и может изменять его свойства. –

+0

Вы говорите ему, чтобы записать в ваш массив байтов, передав в него массив байтов. –

+0

Без объяснения _why_, легко проверить самостоятельно _that_ он работает: http://ideone.com/HrLDZ3 – CompuChip

ответ

3

Передающий ссылочный тип в метод иногда может быть неинтуитивным для разработчиков. Рассмотрим эти два фрагмента кода (ни один из которых используют ref ключевое слово):

void Method1(SomeType myObj) 
{ 
    myObj = new SomeType(); 
} 

void Method2(SomeType myObj) 
{ 
    myObj.SomeProperty = 1; 
} 

Первый метод не имеет побочных эффектов. В метод был передан ссылочный тип, который из-за отсутствия лучшего термина в основном представляет собой «указатель» (сам передается по значению) объекту в памяти. Если вы установите переменную в новый объект в память, оригинал остается неизменным. В памяти есть два объекта. (Хотя новый один уйдет, как только метод заканчивается, потому что ничего не использует его.)

второго метод, однако, делает имеет побочный эффект. Он использует ту же ссылку на объект в памяти, но он модифицирует сам объект. Итак, все, что исследует объект после вызова метода, увидит эту модификацию.


Предположительно, Socket.Receive() делает нечто подобное второму методу выше. Он использует ссылку для изменения объекта.


Чтобы проиллюстрировать, как ref ключевого слова будет изменить:

void Method3(ref SomeType myObj) 
{ 
    myObj = new SomeType(); 
} 

В это сценария, есть и побочный эффект. Любой код, который вызывает этот метод, а затем, после этого, проверяет, что объект, который он отправил методу, будет видеть, что объект был заменен новым. В этом случае не было второго «указателя» в том же месте в памяти. Метод использовал фактический указатель , что используемый код вызова.

+0

Для ясности, почему бы вам не использовать, всегда используйте ref, когда вы изменяете исходный объект? – ThatBrianDude

+1

@ThatBrianDude: Я полагаю, ты * мог *. Честно говоря, такие методы, как «Socket.Receive()», беспокоят меня в этом отношении. Я лично нахожу * неожиданным * для чего-то, что я передаю методу, который нужно изменить. Следуя принципу наименьшего удивления и еще чего-то. Для любого данного метода в рамках, где это происходит, я подозреваю, что существует история того, откуда оно взялось, и почему они это сделали, и теперь это то, что есть, и они не могут ввести разрывное изменение. Но все, что мы пишем сегодня, действительно не должно изменять объект, подобный этому. – David

+0

@ Да, вы должны понять, откуда берется массив, он наследует от 'class Array'. При этом класс будет передан по ссылке;). Рассмотрим этот указатель на C++, и имеет смысл передать ссылку на массив, где будут записаны данные ... –

Смежные вопросы