复制字符串并更改其值不会更改原始值
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
如您所见,a
和 b
指向相同的 内存位置 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.. 这是因为 strings 是 interned.字符串驻留是指在字符串驻留池中拥有每个唯一字符串的单个副本,这是通过散列 table 查找的。这基本上是一种在后台完成的内存节省功能,与问题完全无关。
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
如您所见,a
和 b
指向相同的 内存位置 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.. 这是因为 strings 是 interned.字符串驻留是指在字符串驻留池中拥有每个唯一字符串的单个副本,这是通过散列 table 查找的。这基本上是一种在后台完成的内存节省功能,与问题完全无关。