首页 > 解决方案 > 复制字符串并更改其值不会更改原始值

问题描述

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 时写入更多行。我的文本框已经启用了多行。当我运行我的代码时,文本框没有任何反应:(

标签: c#buttontextbox

解决方案


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

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

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

Text是一个string 属性

tbGameplayMessage.Text

string是一个引用类型,我们知道如果我们复制一个引用,我们有 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它是一个引用类型,而您的变量只持有一个指向实际内存位置的指针(便利贴)。

当你为一个变量分配另一个引用时,你给它一个新的位置来指向内存

这就是为什么当你改变时你不能分配你 tbGameplayMessage.Textgametext期望tbGameplayMessage.Text改变的原因gametext

gametext = tbGameplayMessage.Text;

以上是将引用复制到保存在Text.

当您提供gametext参考时,Text仍然有旧参考(它不会改变)。

让我们更好地了解这一点:

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

神奇的是它再次指向原来的位置。这是因为字符串interned。字符串实习是指在字符串实习池中拥有每个唯一字符串的单个副本,通过哈希表进行查找。这基本上是一个在后台完成的内存节省功能,与问题完全无关。


推荐阅读