C#字节数组受影响throu方法没有引用

时间:2016-07-16 19:20:06

标签: c# sockets

这是一个使用异步Socket接收数据的工作(无用)示例。 完整的代码可以在MSDN找到。

public class Class1
{
    private static void Receive( Socket client )
    {
        StateObject state = new StateObject();
        state.workSocket = client;

        //state.buffer is a empty byte array
        client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReceiveCallback), state);
    }

    private static void ReceiveCallback( IAsyncResult ar )
    {
        StateObject state = (StateObject) ar.AsyncState;
        Socket client = state.workSocket;

        int bytesRead = client.EndReceive(ar);

        //state.buffer contains now all the received data.
        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
    }
}

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

BeginReceive方法中,由于没有state.bufferref关键字,因此无法影响out字段。

但是字节数组实际上已经改变了值。

state.buffer Methode中的Receive字段是如何为空,然后在ReceiveCallback方法中访问时包含所有收到的数据?

2 个答案:

答案 0 :(得分:2)

  

因为没有ref或out关键字

,所以不可能影响state.buffer字段

没有。这不是真的。 state.buffer指向的实际对象可以通过其他方法更改,但其引用不能更改。

这是一个简单的例子:

static void Main()
{
    byte[] arr = new byte[] { 1, 2, 3, 4, 5 };

    ChangeTheObject(arr);

    foreach(byte b in arr) {
         Console.WriteLine(b);
    }
}

static void ChangeTheObject(byte[] arr)
{
     arr[2] = 7;
}

Main()将打印

1
2
7
4
5

对象本身可以通过接收它的方法进行更改。

但是,您无法更改引用本身。

static void ChangeTheReference(byte[] arr)
{
     arr = new byte[] { 6, 7, 8, 9, 10 };
}

这不会更改Main()中原始数组的内容,因为您已重新指定对新对象的本地引用。您没有更改原始对象。这就是ref关键字派上用场的地方。

示例中的方法是更改​​数组的内容,而不是引用。

答案 1 :(得分:0)

如果您花时间至少阅读您发布的MSDN链接上的评论,您就会明白发生了什么:

开始从远程设备接收数据。

client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0, 
     new AsyncCallback(ReceiveCallback), state);

从远程设备读取数据。

int bytesRead = client.EndReceive(ar);

下次,在声明可能与否之前,花更多时间阅读并理解已经解释的内容。