Jer*_*ins 5 c# instance-variables local-variables
ASP.NET 4.0 Webforms项目.我的代码隐藏中有以下内容.
public partial class _Default : System.Web.UI.Page
{
private string testVar;
protected override void OnInit(EventArgs e)
{
string testVar = "test";
}
protected void Page_Load(object sender, EventArgs e)
{
var whatsTheValue = testVar;
}
}
Run Code Online (Sandbox Code Playgroud)
我在每个方法中设置一个断点.当局部变量testVar,被设置在OnInit,如果我快看实例变量,它也有值"测试".当我玩到时Page_Load,实例变量的值是null.
我偶然碰到了这个,但这种行为让我感到困惑.我真的很惊讶它编译.我本来希望看到有关两个变量具有相同名称的警告.话虽如此,对我来说更令人困惑的是,实例变量在OnInit中获取赋值,但是当退出该方法时立即丢失它.
有人可以向我解释这种行为吗?
Eri*_*ert 13
BrokenGlass的答案当然是正确的; 你不是首先看场.当地隐藏了这个领域.
但是,我注意到没有人解决你问题的这一部分:
我真的很惊讶它编译.我本来希望看到有关两个变量具有相同名称的警告.
在这种情况下,C#编译器不会发出错误或警告,因为这样做会产生"脆弱的基类失败"的形式.假设你有这个代码:
class B { }
class D : B
{
void M()
{
int x;
...
Run Code Online (Sandbox Code Playgroud)
B由您组织中的一个团队制作,D由完全不同的团队制作.然后有一天,B的维护者决定添加一个需要受保护字段的功能:
class B { protected int x; }
Run Code Online (Sandbox Code Playgroud)
重新编译D时,是否应该出错? 如果确实如此,那么完全不同的团队中的某个人就会破坏您的代码!C#经过精心设计,可以最大限度地减少(尽管不能消除)这种破损.
请注意,如果在同一代码块中重复使用x表示两个不同的东西,C#确实会出错.例如:
class B { protected int x; }
class D : B
{
void M()
{
x = 123; // meaning this.x inherited from B
if (whatever)
{
int x = 10;
...
Run Code Online (Sandbox Code Playgroud)
这是非法的,因为现在在M的主体中,简单名称x用于表示两者this.x 和局部变量x.因为这可能令人困惑并且编程实践不好,所以我们将其视为错误.但是,如果你真的想要那么你可以通过确保使用*完全独立的块来消除错误:
class B { protected int x; }
class D : B
{
void M()
{
{
x = 123; // meaning this.x inherited from B
}
if (whatever)
{
int x = 10;
Run Code Online (Sandbox Code Playgroud)
现在块不重叠,因此编译器假定您知道自己在做什么并允许代码进行编译.
如果我快速观察实例变量,它也有值"test".当我播放到Page_Load时,实例变量的值为null.
您没有看到实例变量,您会看到局部变量.永远不会设置实例变量,因为本地范围的变量在其范围生存期内隐藏了实例变量.
从规格:
3.7.1名称隐藏
实体的范围通常包含比实体的声明空间更多的程序文本.特别是,实体的范围可能包括引入包含同名实体的新声明空间的声明.此类声明会导致原始实体隐藏.相反,当一个实体未被隐藏时,它被认为是可见的.
当范围通过嵌套重叠并且范围通过继承重叠时,会发生名称隐藏.以下各节描述了两种隐藏的特征.
由于在类或结构中嵌套类型以及作为参数和局部变量声明的结果,在命名空间内嵌套命名空间或类型,可能会发生通过嵌套隐藏的名称
| 归档时间: |
|
| 查看次数: |
2659 次 |
| 最近记录: |