C# 基本.NET-如何引用';存储/解析';
请注意以下代码:C# 基本.NET-如何引用';存储/解析';,c#,asp.net,pointers,reference,C#,Asp.net,Pointers,Reference,请注意以下代码: Control foo = null; Control bar = null; int i = 0; protected void Page_Load(object sender, EventArgs e) { test(); test(); Page.Controls.Add(foo); } void test() { i++; bar = new Control(); bar.Controls.Add(new Litera
Control foo = null;
Control bar = null;
int i = 0;
protected void Page_Load(object sender, EventArgs e)
{
test();
test();
Page.Controls.Add(foo);
}
void test()
{
i++;
bar = new Control();
bar.Controls.Add(new LiteralControl(i.ToString()));
if (foo == null)
{
foo = new Control();
foo.Controls.Add(bar);
}
}
在尝试上面的代码时,我惊讶地看到打印的结果是“1”(而不是“2”)
我假设这是因为当我向foo
添加控件bar
时,foo.Controls.Add()
解析引用bar
,而不仅仅是存储引用本身
1) 有人能证实这一点吗,或者可能详细说明一下
2) 我有一种感觉,如果我被允许做
foo.Controls.Add(参考条)代码>它将显示“2”,但显然该语法是非法的。在不进行重大重构的情况下,是否可能出现这种情况 比这简单多了。foo是类作用域的对象。第二次运行test()时,它不会发生任何变化,因为它不是null。所以它只是返回您从第一个test()添加到它的内容,这是一个字符串值为“1”的新LiteralControl。“1”只是文本,它不是对i的引用
顺便说一下,foo.Controls.Add(参考条)
实际上就是这样。控件(对象)始终通过引用添加,这是其存在的本质。要将对象的实际值传递给某个对象,基本上必须先复制该对象。但你还是会传递一个副本的引用
如果您更改了条的内容
,它确实会更改输出
我认为您在这里感到困惑的是,您在第二次运行test()时没有处理相同的bar
,因为每次都会创建一个新的
(编辑)
顺便说一下,如果您只更改了这一行:
bar = new Control();
到
它的行为将如预期的那样,因为第二次通过您不会像现在这样用一个新的引用替换掉原来的“bar”引用。(Sorta…实际上它会说“12”,因为你会在其中添加两个LiteralControl)。调用
foo.Controls.Add(bar);
使用条的当前值
。这是指包含文本为“1”的文字控件的控件
现在稍后,您将更改bar
的值以引用一个完全不同的控件。。。但是这与foo.Controls
中已经存储的内容没有任何区别。即使您可以通过引用将bar
传递到Add
方法中,实际上也不会有任何区别
我强烈建议,如果您不确定引用、参数等在.NET中如何工作,请使用控制台应用程序检查您的理解。它们更易于使用、调试等
您可能还想阅读我关于和的文章。第一次运行test()
时,将创建一个新控件(我称之为Control1
),并在栏中存储对它的引用。因为foo
为空,所以它被设置为一个新控件,其中添加了条中的引用
所以现在Control1
现在被bar
和foo.Controls集合引用
第二次运行test()foo
现在不为空,因此不进行修改
所以现在bar
是对Control2
的引用,但是foo。Controls
仍然包含对Control1
的引用。foo只创建一次(在第一次调用test时),然后添加标签为1的LiteralControl
在第二次调用test()时,旧引用(标签1)将替换为新控件。但是,添加到foo中的条仍然存在并且没有受到影响。Jon Skeet的回答是好的(当然),但我只想强调一点:
引用类型的变量(如bar和foo)不包含对象,它们包含对对象的引用。
因此,第一次通过test()方法,bar包含对控件的引用,该控件中有一个1。这个引用被添加到foo中
第二次使用test()方法时,bar包含对另一个控件的引用,该控件中有一个2。而该引用不会添加到foo中
为什么第二次是不同的参考?因为在test()的开头,你说bar=newcontrol()代码>,用于在条形图中存储对新控件的引用。从那时起,bar与它之前提到的控件无关,尽管对该控件的引用仍然存在于foo的Controls集合中
如果要更改代码,使其符合预期,可以执行以下操作:
Control foo = null;
Control bar = new Control();
int i = 0;
protected void Page_Load(object sender, EventArgs e)
{
test();
test();
Page.Controls.Add(foo);
}
void test()
{
i++;
bar.Controls.Clear()
bar.Controls.Add(new LiteralControl(i.ToString()));
if (foo == null)
{
foo = new Control();
foo.Controls.Add(bar);
}
}
在这种情况下,我们一次只在bar中存储一个新引用,所以当所有操作都完成时,它应该仍然与我们添加到foo中的引用相匹配
Control foo = null;
Control bar = new Control();
int i = 0;
protected void Page_Load(object sender, EventArgs e)
{
test();
test();
Page.Controls.Add(foo);
}
void test()
{
i++;
bar.Controls.Clear()
bar.Controls.Add(new LiteralControl(i.ToString()));
if (foo == null)
{
foo = new Control();
foo.Controls.Add(bar);
}
}