考虑以下功能:
public static bool TryToDoStuff(ReadOnlySpan<byte> input, Span<byte> destination) {
...
}
此函数根据destination
的内容返回是否能够在input
上执行操作。
我想检查内存区域是否被 input
和destination
“包裹”,并且如果相交,则抛出异常,因为这会破坏{ {1}}的数据。 我该如何做(没有反射或不安全的代码)?
我知道我可以编写一些xmldoc并警告用户这些参数不应相交,但这是一个穷人的解决方案。
编辑:对于那些要求示例的人,沃兹纳的示例很重要。
input
答案 0 :(得分:3)
有一种使用System.Runtime.CompilerServices.Unsafe
NuGet程序包的方法。它提供了ByteOffset
和SizeOf
之类的低级方法。
使用这些方法,您可以编写以下方法:
public static bool Intersects<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b)
{
var elementSize = Unsafe.SizeOf<T>();
var distance = (long)Unsafe.ByteOffset<T>(ref MemoryMarshal.GetReference(a), ref MemoryMarshal.GetReference(b));
if (distance < 0)
{
return -distance < b.Length * elementSize;
}
else if (distance > 0)
{
return distance < a.Length * elementSize;
}
return true;
}
此方法确定每个跨度中第一个元素之间的距离(以字节为单位)。然后确定距离是否小于跨度中的项数乘以跨度中单个元素的大小(以字节为单位)。
通过使用Unsafe.SizeOf<T>
,我们甚至允许在非原始类型上使用此方法。诸如字符串和类之类的引用类型是本机整数(IntPtr.Size
)的大小。
下面一些表明该方法有效的测试用例:
// On arrays
Span<byte> firstArray = new byte[10];
Span<byte> secondArray = new byte[10];
Intersects<byte>(firstArray.Slice(5, 5), firstArray.Slice(3, 5)); // true
Intersects<byte>(firstArray.Slice(5, 5), secondArray.Slice(3, 5)); // false
// And on stackallocated memory
Span<byte> firstStack = stackalloc byte[10];
Span<byte> secondStack = stackalloc byte[10];
Intersects<byte>(firstStack.Slice(5, 5), firstStack.Slice(3, 5)); // true
Intersects<byte>(firstStack.Slice(5, 5), secondStack.Slice(3, 5)); // false
注意:System.Runtime.CompilerServices.Unsafe
软件包需要使用ref-returns,这是一个仅从C#7开始可用的功能
答案 1 :(得分:2)
我在dotnet / corefx存储库上创建了一个问题,其中一位贡献者发布了此链接:
https://docs.microsoft.com/en-us/dotnet/api/system.memoryextensions.overlaps?view=netcore-2.1
是的,有一个优雅,简洁,安全且框架内的解决方案。
答案 2 :(得分:0)
“不使用反射或不安全的代码”-不可能,因为_pointer
的{{1}}属性没有以任何方式公开公开: