代码之家  ›  专栏  ›  技术社区  ›  Simsons

在结构内创建数组时,该结构是否直接包含数组的值或对该数组的内存引用?

  •  0
  • Simsons  · 技术社区  · 14 年前

    我正在创建一个数组,如下所示:

    public struct Smb_Parameters
            {
                public byte WordCount;
                public ushort[] Words;
            }
    

    当我分配如下值时:

    Smb_Parameters smbParameter = new Smb_Parameters();
    smbParameter.WordCount = 0;
    string words= "NT LM 0.12";
    smbParameter.Words = Encoding.ASCII.GetBytes(name);
    

    在上述任务中 smbParameter.WordCount 包含值 0 但确实 smbParameter.Words 直接包含值(字节数组)或对包含值的位置的内存引用?

    编辑1 :

    我想给服务器发送一个包。为了这个我需要转换 Smb_Parameters 要使用以下代码进行数组的对象:

    int len = Marshal.SizeOf(Smb_Parameters);
     byte[] arr = new byte[len];
     IntPtr ptr = Marshal.AllocHGlobal(len);
     Marshal.StructureToPtr(Smb_Parameters, ptr, true);
     Marshal.Copy(ptr, arr, 0, len);
     Marshal.FreeHGlobal(ptr);
    
    1 回复  |  直到 14 年前
        1
  •  3
  •   Jon Skeet    14 年前

    除非你使用 fixed-size buffers 在不安全代码中,它将是一个引用。一般来说,变量是否包含在结构或类中并不重要,或者实际上它是否是局部变量:变量的类型决定值是引用还是直接包含数据。除了我提到的固定大小的缓冲区,数组在.NET中总是引用类型。

    (还有) stackalloc 它看起来有点像数组分配——它在堆栈上分配一块内存。同样,这只用于不安全的代码,在我的经验中很少遇到。)

    在您给出的示例中(适当地调整以使其编译) Words 肯定是个参考。尤其是,如果将值赋给引用特定数组的对象,然后更改该数组的内容,则这些更改将通过结构的变量可见。

    (我也强烈建议你 不要 具有公共字段或可变值类型。希望这只是为了一个例子,不过:)

    编辑:要回答更新的问题, 不要这样发送数据 . 这是一种非常脆弱的序列化方式。有多种更好的选择:

    • 使用.NET二进制序列化(在版本控制方面也有些脆弱,而不是跨平台)
    • 使用XML序列化(在本例中可能是杀戮过度)
    • 使用第三方序列化框架(例如节俭或协议缓冲区)
    • 在类中使用“ToBytearray”或“WriteToStream”方法手动滚动序列化,该方法显式序列化每个值。你可能想用 BinaryWriter 为此。