结构行为中的字符串

本文关键字:字符串 结构 | 更新日期: 2023-09-27 18:33:14

假设我们有结构

struct MyStruct
{
    public string a;
}

当我们将其分配给新变量时,字符串会发生什么?因此,例如,我们希望在堆栈中复制结构时应共享字符串。我们使用此代码来测试它,但它返回不同的指针:

    var a = new MyStruct();
    a.a = "test";
    var b = a;
    IntPtr pA = Marshal.StringToCoTaskMemAnsi(a.a);
    IntPtr pB = Marshal.StringToCoTaskMemAnsi(b.a);
    Console.WriteLine("Pointer of a : {0}", (int)pA);
    Console.WriteLine("Pointer of b : {0}", (int)pB);

问题是当结构在堆栈中复制并且内部有字符串时,它是共享字符串还是重新创建字符串?

[更新]

我们也尝试了这段代码,它也返回不同的指针:

    char charA2 = a.a[0];
    char charB2 = b.a[0];
    unsafe
    {
        var pointerA2 = &charA2;
        var pointerB2 = &charB2;

        Console.WriteLine("POinter of a : {0}", (int)pointerA2);
        Console.WriteLine("Pointer of b : {0}", (int)pointerB2);
    }

结构行为中的字符串

用于测试它的代码 根据 MSDN,"将托管字符串的内容复制到从非托管 COM 任务分配器分配的内存块。如果任何两个后续调用StringToCoTaskMemAnsi都会返回相同的指针,我会感到惊讶。您可以查看两个字符串引用的内存地址,或使用调试器分配对象 ID。或更简单:object.ReferenceEquals(a.a, b.a);

在您的更新中,您指向字符变量的堆栈位置,也不是找出答案的好方法。在任何情况下,当您将一个字符串分配给另一个字符串时,您只是复制引用,因此它们应该始终相同。

字符串在存储和引用类型中是不可变的。此外,在您的示例中,字符串"test"被暂留。因此,无论您创建多少个结构副本,您最终都会有多个指向同一底层存储的指针(除非您通过回旋将其复制到您人为示例正在执行的新内存块)

请放心,只有一个副本,指向多次。