复制字符串并更改其值不会更改原始值

Copying a string and changing its value doesn't change the original value

public string gametext;

public Gameplay()
{
    InitializeComponent();
    gametext = tbGameplayMessage.Text;
}

private void button_Click(object sender, EventArgs e)
{
    gametext += "Write textbox \r\n";
}

private void button2_Click(object sender, EventArgs e)
{
    gametext += "Write textbox \r\n";
}

这是我的代码,我想做的是每次单击按钮时更新文本框,并在单击按钮 2 时写入更多行。 我的文本框已经启用了多行。 当我 运行 我的代码时,文本框没有任何反应:(

您的问题的解决方法是直接更新 Text 属性:

private void button_Click(object sender, EventArgs e)
{
    tbGameplayMessage.Text+= "Write textbox \r\n";
}

让我们来看看发生了什么。

Text 是一个 string 属性:

tbGameplayMessage.Text

string 是一个 reference type,我们知道如果我们复制一个引用,我们有 2 个变量指向内存中的相同位置。

让我们看看实际效果:

// create a string
var a = "test1";
// copy a to b
var b = a;

// this is just a way of getting our strings position in memory 
fixed (char* pa = a,pb = b)
{
   Console.WriteLine($"a : {a} @ {(uint)pa}"); 
   Console.WriteLine($"b : {b} @ {(uint)pb}");
}

输出

a : test1 @ 51748
b : test1 @ 51748

如您所见,ab 指向相同的 内存位置 51748。好的到目前为止一切顺利

但是当我们将新字符串 ("test2") 分配给 a

时,请注意会发生什么
a = "test2";

fixed (char* pa = a, pb = b)
{
   Console.WriteLine($"a : {a} @ {(uint)pa}");
   Console.WriteLine($"b : {b} @ {(uint)pb}");
}

输出

a : test2 @ 51876
b : test1 @ 51748

注意 b 仍然包含原始 string test1 并指向相同的 位置 ,但 a 已被占用我们的新 string,指向不同的 位置

这是因为 string 是一个引用类型,而您的变量仅持有指向实际内存位置的指针(post-it-note)。

当您将另一个引用分配给一个变量时,您就是在给它一个指向内存中的新位置

这就是为什么您不能将 tbGameplayMessage.Text 分配给 gametext 并期望 tbGameplayMessage.Text 在您更改 gametext

时更改的原因
gametext = tbGameplayMessage.Text;

上面是将reference复制到Text.

中保存的字符串

当您给 gametext 一个新的 reference 时,Text 仍然有旧的 reference(它没有'改变)。

让我们更好地了解一下:

var a = "test";
for (int i = 0; i < 5; i++)
{
   a += i;

   fixed (char* pa = a)
   {
      Console.WriteLine($"a : {a} @ {(uint) pa}");
   }
}

输出:

a : test10 @ 67684
a : test101 @ 67812
a : test1012 @ 67940
a : test10123 @ 68068
a : test101234 @ 68196

每次我们触摸字符串时,它都会指向不同的位置。


现在有一个额外的事实,如果我们将 "test1" 分配回 a 看看会发生什么:

a = "test1";

fixed (char* pa = a, pb = b)
{
   Console.WriteLine($"a : {a} @ {(uint)pa}");
   Console.WriteLine($"b : {b} @ {(uint)pb}");
}

输出

a : test1 @ 51748
b : test1 @ 51748

它神奇地再次指向原来的 location.. 这是因为 stringsinterned.字符串驻留是指在字符串驻留池中拥有每个唯一字符串的单个副本,这是通过散列 table 查找的。这基本上是一种在后台完成的内存节省功能,与问题完全无关。