C#: Почему Networkstream.Read() может изменить буферную переменную без ключевого слова out/ref

Почему NetworkStream.Read() может записать в байт []?

byte[] data = new byte[16];

NetworkStream ns = new NetworkStream(socket);
ns.Read(data, 0, data.Length);

//data != new byte[16]

Я думал, что вам нужно ключевое слово out/ref для записи в переменную. как это:

ns.Read(out data, 0, data.Length);

Если я пытаюсь воссоздать этот метод, он не работает:

public static void testread(byte[] buffer, int size)
{
    byte[] data = new byte[size];
    for (int i = 0; i < data.Length; i++)
    {
        data[i] = 1;
    }
    buffer = data;
}

byte[] data = new byte[16];
testread(data, data.Length);

//data == new byte[16]

Но если я добавлю ключевое слово "out" в testread(), это сработает:

public static void testread(out byte[] buffer, int size)
{
    byte[] data = new byte[size];
    for (int i = 0; i < data.Length; i++)
    {
        data[i] = 1;
    }
    buffer = data;
}

byte[] data = new byte[16];
testread(data, data.Length);

//data != new byte[16]

Это доказывает, что вы не можете писать в переменную без ключевого слова "out"/"ref". Но как NetworkStream записывает в byte[] без ключевого слова "out"/"ref"? Страшно..

2 ответа

Решение

Это доказывает, что вы не можете писать в переменную без ключевого слова "out"/"ref".

Вам нужно мысленно разделить два совершенно разных понятия:

  • изменение состояния объекта
  • переназначение значения переменной (параметр, локальный, поле и т. д.)

(отмечая, что в случае объектов последний означает изменение объекта, на который он ссылается)

out нужен только для второго из них. Stream позволяет вызывающей стороне передать объект (массив), и он записывает в массив. нет out нужен для этого. Это ничем не отличается от:

void SetCustomerName(Customer obj) { // for class Customer
    obj.Name = "Fred";
}
...
var x = new Customer();
SetCustomerName(x);
Console.WriteLine(x.Name); // prints "Fred"

Это обновляет объект, но для этого не нужно изменять параметр. Изменяет объект, на который указывает параметр.

Скорее всего, потому что это не делает buffer = data назначение. Вместо этого он читает непосредственно в буфер, переданный в качестве аргумента, т.е. если вы делаете buffer[i] = 1 в вашем цикле вы имитируете это.

Другие вопросы по тегам