gpt4 book ai didi

c# - 如何从只读结构中获取 ReadOnlySpan

转载 作者:行者123 更新时间:2023-12-01 23:10:08 28 4
gpt4 key购买 nike

以下代码会导致编译器在属性 getter 的第一行抛出错误 CS1605(“无法将 'var' 作为 ref 或 out 参数传递,因为它是只读的”)。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct MyStruct
{
public readonly int Field1;
public readonly int Field2;

public MyStruct(int field1, int field2) => (Field1, Field2) = (field1, field2);

public ReadOnlySpan<byte> Span
{
get
{
// This code only works when MyStruct is not read only
ReadOnlySpan<MyStruct> temp = MemoryMarshal.CreateReadOnlySpan(ref this, 1);
return MemoryMarshal.Cast<MyStruct, byte>(temp);
}
}
}

删除readonly来自public readonly struct MyStruct line 使代码可以工作,但出于性能原因,我真的希望该结构为 readonly 。它使代码比必须将结构传递为 ref 更加干净。一直以来。

有没有办法获得 ReadOnlySpan<byte>来自只读结构?

编辑:...不创建结构的隐式或显式副本?

最佳答案

看起来这可行:

// The following code will work from C# 7.3 and up, no unsafe keyword required
Span<MyStruct> span = stackalloc MyStruct[1];
span[0] = new MyStruct(3, 4);
var bytes = MemoryMarshal.Cast<MyStruct, byte>(span);

如果我们想将其公开为属性,我们可以尝试以下操作:

// Will not work at runtime
public ReadOnlySpan<byte> Span
{
get
{
unsafe
{
fixed (MyStruct* ptr = &this)
{
return new ReadOnlySpan<byte>(ptr, sizeof(MyStruct)); // If on the heap, we're doomed as returning will unpin the memory.
}
}
}
}

并将该结构标记为只读引用结构,这再次保护了我们堆上的结构。它可以编译,但不会运行,因为您在运行时收到 AccessViolationException 。我会做更多的挖掘,看看是否可能,这在逻辑上应该是安全的,但今天可能不可能。

另一个折衷的解决方案是将其保留为只读结构(而不是ref struct)并添加此静态方法:

public static unsafe ReadOnlySpan<byte> GetSpan(ref MyStruct myStruct)
{
return new ReadOnlySpan<byte>(Unsafe.AsPointer(ref myStruct), sizeof(MyStruct));
}

然后从调用代码:

var myStruct = new MyStruct(1, 2);
var span = MyStruct.GetSpan(ref myStruct);

我们可以通过将其移出到引用扩展方法中来改进它的使用(C# 7.2 功能):

class Program
{
static void Main()
{
var myStruct = new MyStruct(1, 2);
var span = myStruct.GetSpan();
}
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct MyStruct
{
public readonly int Field1;
public readonly int Field2;

public MyStruct(int field1, int field2) => (Field1, Field2) = (field1, field2);
}

public static class MyStructExtensions
{
public static unsafe ReadOnlySpan<byte> GetSpan(ref this MyStruct myStruct)
{
return new ReadOnlySpan<byte>(Unsafe.AsPointer(ref myStruct), sizeof(MyStruct));
}
}

关于c# - 如何从只读结构中获取 ReadOnlySpan<byte> ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59020436/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com