【问题标题】:C# byte array is affected throu Method without referenceC# 字节数组通过没有参考的方法受到影响
【发布时间】:2016-07-16 19:20:05
【问题描述】:

这是一个使用异步 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.buffer 字段,因为没有refout 关键字。

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

ReceiveMethode 中的state.buffer 字段怎么可能是空的,然后在ReceiveCallback 方法中访问时包含所有接收到的数据?

【问题讨论】:

  • 在这种情况下,buffer 是一个数组。数组引用本身没有改变,但是数组的内容仍然是可变的。
  • Passing By ref and out的可能重复
  • 如果它正常工作,它是一个无用的例子吗?
  • @cFrozenDeath 我只是添加了无用的,因为 StringBuilder 的内容没有被返回使用或其他东西。

标签: c# sockets


【解决方案1】:

应该不可能影响 state.buffer 字段,因为没有 ref 或 out 关键字

没有。这不是真的。 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 关键字会派上用场的地方。


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

【讨论】:

    【解决方案2】:

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

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

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

    从远程设备读取数据。

    int bytesRead = client.EndReceive(ar);
    

    下一次,在声明可能或不可能之前,花更多时间阅读和理解已经解释的内容。

    【讨论】:

      猜你喜欢
      • 2016-02-14
      • 2018-08-10
      • 2019-07-29
      • 1970-01-01
      • 1970-01-01
      • 2017-06-30
      • 1970-01-01
      • 2013-08-28
      • 2017-11-15
      相关资源
      最近更新 更多