实现Amazon Glacier Tree Hash时关于Memory<T>底层数组访问、HashAlgorithm适配及SonarQube Roslyn警告处理的技术问询
问题2:存储在Memory实例中的数据是否也可以通过用于创建它的原数组访问?
完全可以。当你用new Memory<byte>(buff)创建Memory<T>时,它只是原数组的一个"视图",没有复制任何数据。写入Memory<T>的内容会直接同步到原数组中,反之亦然。
举个直观的例子:
byte[] buff = new byte[3] {1,2,3}; Memory<byte> memory = new Memory<byte>(buff); memory.Span[0] = 100; // 此时buff[0]的值也变为100 Console.WriteLine(buff[0]); // 输出100
你可以通过memory.TryGetArray(out ArraySegment<byte> segment)验证:segment.Array就是原数组,segment.Offset是Memory<T>在数组中的起始索引,segment.Count是Memory<T>的长度。
问题3:是否存在无需复制数据即可将Memory实例中的数据作为数组访问的其他方式?
最安全且通用的方式是使用Memory<T>.TryGetArray方法,它能获取到Memory<T>底层的ArraySegment<byte>,通过这个段你可以直接访问原数组,完全不需要复制:
if (memory.TryGetArray(out ArraySegment<byte> segment)) { // 直接访问原数组的指定范围 byte firstByte = segment.Array[segment.Offset]; // 也可以传入你原有的ComputeHash方法 chunkHashes[idx++] = this.ComputeHash(segment.Array, segment.Offset, bytesRead); }
这个方法的优势在于:如果Memory<T>不是基于托管数组(比如来自非托管内存),TryGetArray会返回false,你可以做降级处理(比如复制数据)。但在你的场景中,Memory<T>是用自己创建的byte[]初始化的,所以肯定会返回true,可以放心使用。
问题4:若以上方案均不可行,如何在SonarQube中屏蔽该外部Roslyn警告?
如果暂时无法修改代码,你可以通过代码层面的编译指令精准屏蔽这个警告,不会影响其他规则的检查:
- 确认警告的规则ID:你遇到的是Roslyn的
CA1835规则(推荐使用ReadAsync/WriteAsync的Memory<T>重载)。 - 在需要屏蔽的代码块前后添加指令:
#pragma warning disable CA1835 // 临时屏蔽该警告 byte[] buff = new byte[Mio]; int bytesRead; while ((bytesRead = await inputStream.ReadAsync(buff, 0, Mio)) > 0) { // Process the bytes read } #pragma warning restore CA1835 // 恢复警告检查
如果整个项目都不需要这个规则,也可以在项目文件(.csproj)中添加全局配置:
<PropertyGroup> <NoWarn>CA1835</NoWarn> </PropertyGroup>
注意:不推荐在SonarQube服务器全局关闭规则,除非团队一致认为该规则不适用,否则会影响其他代码的质量检查。
内容的提问来源于stack exchange,提问作者Nathan.Eilisha Shiraini
相关产品推荐
相关产品推荐

