我有一个c#类,它包装了一个UDP套接字,使接收和处理网络数据更容易。
无论何时接收到数据,都将使用作为参数传递的数据触发一个事件:
public event Action<byte[]> DataReceived = delegate(byte[] data) { };
我接收数据并像这样触发事件:
while (socket.IsBound)
{
var buffer = new byte[MaximumDataLength];
socket.Receive(buffer);
DataReceived(buffer);
}
我的理解是相同的数组实例被传递给每个事件处理程序。
如果其中一个处理程序修改了,这会导致问题吗在其他处理程序处理它之前的数组?
如果是这样,有什么好的补救方法吗?
如果您有选项,则将其设置为IEnumerable<byte>
,如:
Action<IEnumerable<byte>> DataReceived = (d) => { ... }
然后你可以用任何可枚举的对象调用它,但是委托得到的是一种不可修改的形式。
(如果这对你不起作用,总是有ReadOnlyCollection<T>
)
澄清:
由于数组实现了IEnumerable<>
(从。net 2.0开始),您可以将byte[]
直接传递给处理程序:
byte[] buffer = SomeReadFunction();
DataReceived(buffer);
如果你想让它对阅读代码的人显式,你可以强制转换:
DataReceived((IEnumerable<byte>)buffer);
方法1
使用Array.AsReadOnly<T>
扩展方法以有效的方式创建ReadOnlyCollection<T>
。
https://msdn.microsoft.com/en-us/library/53kysx7b (v = vs.110) . aspx
方法2
您可以为ArraySegment<T>
实现一个包装器,使其成为只读的,正如这个答案所建议的。
与列表或其他集合相比,使用ArraySegment有很多好处。
ArraySegment
一个典型的想法可能是创建字节数组的副本,但这可能不适合您,因为每个事件处理程序仍然访问相同的副本。
尝试通过坚持使用。net开发人员熟悉的模式(就像你已经拥有的那样)来避免这个问题——数组原语被传递并相信其他代码不会做奇怪或恶意的事情通常是可以接受的——. net框架中充满了这种情况。