【问题标题】:String inside structure behavior字符串内部结构行为
【发布时间】:2014-12-04 23:28:01
【问题描述】:

假设我们有结构

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);
    }

【问题讨论】:

    标签: c# .net string pointers


    【解决方案1】:

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

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

    【讨论】:

    • “无论如何,当您将一个字符串分配给另一个字符串时,您只是在复制引用,因此它们应该始终相同”,但它在输出中返回不同的指针。
    • @JevgenijNekrasov 您测试它的方式将始终确保不同的指针,无论输入如何。看看我在答案中第一段的最后一句话,要么使用ReferenceEquals 进行检查,要么使用 VS 调试器。
    【解决方案2】:

    字符串在存储和引用类型中是不可变的。此外,在您的示例中,字符串“test”是interned。因此,无论您制作了多少个结构副本,您最终都会有多个指向同一个底层存储的指针(除非您通过旋转将其复制到您设计的示例正在执行的新内存块中)

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      • 2011-12-06
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      相关资源
      最近更新 更多