【问题标题】:Better solution to allocate buffer for array within structure for C#?为 C# 结构内的数组分配缓冲区的更好解决方案?
【发布时间】:2021-08-12 07:17:43
【问题描述】:

我是 C# 初学者,有一个问题。

在C编程中,我知道我可以参考以下代码来读取/写入结构成员中的数组数据,而结构有很多成员,如A[128]B[128],...,M[64]N[128],...,X[32],Y[32],Z[128],...,主代码无需添加分配缓冲区代码即可访问缓冲区数组,简单明了。

struct myStructB{
    int cnt;
    float AA[32];
    float BB[32];
    float CC[128];
};

struct myStructA{
    int cnt;
    int A[128];
    int B[128];
    int C[32];
    ...
    int M[64];
    int N[128];
    ...
    int Z[128];
    myStructB strctB;
};

myStructA testStruct;
int _tmain(int argc, _TCHAR* argv[])
{
    testStruct.A[0] = 123;
    testStruct.B[0] = 456;
    testStruct.C[0] = 789;
    testStruct.strctB.AA[0] = 321;
    testStruct.strctB.BB[0] = 654;
    testStruct.strctB.CC[0] = 987;
    
    int sss = testStruct.strctB.AA[0];
    return 0;
}

在C#中,我想我应该为结构内的数组分配缓冲区,如下所示,如果结构有很多数组元素,代码并不简单,必须分配所有数组成员。我认为这不是一个好主意.....有更好的解决方案来改进此代码吗?我想将此结构对象传递给 C++ DLL。谢谢:)

[StructLayout(LayoutKind.Sequential)]
struct myStructB{
    public int cnt;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public int[] AA;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public int[] BB;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
    public int[] CC;
}

[StructLayout(LayoutKind.Sequential)]
struct myStructA{
    public int cnt;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public int[] A;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public int[] B;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
    public int[] C;
    ...
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    public int[] M;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public int[] N;
    ...
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public int [] Z;
    ...
    public myStructB strctB; 
}

myStructA testStruct = new myStructA();
testStruct.A = new int[128];
testStruct.B = new int[128];
testStruct.C = new int[32];
...
testStruct.M = new int[64];
testStruct.N = new int[128];
...
testStruct.Z = new int[128];

testStruct.strctB.AA = new int[128];
testStruct.strctB.BB = new int[128];
testStruct.strctB.CC = new int[32];

testStruct.A[0] = 123;
testStruct.B[0] = 456;
testStruct.C[0] = 789;
testStruct.strctB.AA[0] = 321;
testStruct.strctB.BB[0] = 654;
testStruct.strctB.CC[0] = 987;

【问题讨论】:

    标签: c# arrays c


    【解决方案1】:

    如果您想将整个数组嵌入到结构本身中,您可以使用固定缓冲区:

    public unsafe ref struct MyStructB
    {
        public const int Cnt = 128;
        public fixed float AA[Cnt/4];
        public fixed float BB[Cnt/4];
        public fixed float CC[Cnt];
    }
    
    public unsafe ref struct myStructA
    {
        public const int Cnt = 32;
        public fixed float AA[Cnt];
        public MyStructB structB;
    };
    

    ref 表示 MyStruct 不能装箱。它强制 MyStruct 始终在堆栈上分配。这不是必须的,但你可以考虑一下。

    用法:

    unsafe
    {
        var x = new MyStructB();
        // Accessing the first element AFTER AA, so you see why this is unsafe ;)
        x.AA[32] = 100;
        Console.WriteLine(x.BB[0]);  // 100; welcome to good old C
    }
    

    在您的项目设置中,您必须允许不安全的块(csproj 文件):

      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
      </PropertyGroup>
    

    因此,我将创建一个自己的包装库来最小化允许不安全执行的范围。

    【讨论】:

    • 嗨,迈克尔,你的代码编译有错误 => 预期的类、委托、枚举、接口或结构
    • 无法重现此错误。我已将整个 Program.cs 复制到 dotnetfiddle.net/TJghDb(无法在线编译,因为 dotnetfiddle 没有不安全模式)
    • ref struct 需要 C# 7.2,这可能是此错误的原因。尝试删除参考。
    • 它正在工作!我认为您为我提供了一个很好的解决方案。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多