在 switch 语句中变量作用域奇怪

15

这个问题让我想起了我心中一个有关 switch 的老问题,一直没有得到答案:

    int personType = 1;
    switch (personType)
    {
        case 1:
            Employee emp = new Employee();
            emp.ExperienceInfo();
            break;
        case 2:
            Employee emp = new Employee(); 
            //Error: A local variable named 'emp' is already defined in this scope
            emp.ManagementInfo();
            break;
        case 3:
            Student st = new Student();
            st.EducationInfo();
            break;
        default:
            MessageBox.Show("Not valid ...");
    }

为什么在'case 2'中会识别emp?在C++中(如果我没记错的话)我们可以一起使用多个cases,但在C#中这是不可能的,我们需要使用break来关闭case 1,所以在C++中以下代码看起来是正确的而在C#中则是错误的:

case 1:
case 2:
   SomeMethodUsedByBothStates();

如果我们不能在case 1中声明并在case 2中看到emp,那么为什么应该允许这样的行为?如果永远不会同时发生两种情况,那么为什么对象应该在两种情况下都可见?

4个回答

34

在C++或C#中,case语句块不会创建作用域。所有在case语句块内声明的变量都属于同一个作用域,即switch语句的作用域。如果你希望这些变量只在特定的case语句块内生效,你需要使用花括号来明确指定作用域:

switch (personType)
{
    case 1: {
        Employee emp = new Employee();
        emp.ExperienceInfo();
        break;
    }
    case 2: {
        Employee emp = new Employee(); 
        // No longer an error; now 'emp' is local to this case.
        emp.ManagementInfo();
        break;
    }
    case 3: {
        Student st = new Student();
        st.EducationInfo();
        break;
    }
    ...
}

5
您展示的第二个代码在C#中完全没有问题,假设情况2有一个“break”或“return”:
case 1:
    // no code here...
case 2:
    SomeMethodUsedByBothStates();
    break;

允许空的 case 穿透。
但是,在 case 分支中有穿透的代码是无效的。因此,以下内容是无效的:

case 1:
    SomeMethodUsedOnlyByCase1();
    // no break here...
case 2:
    SomeMethodUsedByBothStates();
    break;

关于作用域的问题是一个不同的问题。 基本上,作用域是 switch 语句本身,而不是 case 分支。

为了使您的示例编译,只需添加花括号给 case 分支以独立的作用域:

int personType = 1;
switch (personType)
{
    case 1:
    {
        Employee emp = new Employee();
        emp.ExperienceInfo();
        break;
    }
    case 2:
    {
        Employee emp = new Employee(); 
        emp.ManagementInfo();
        break;
    }
    case 3:
    {
        Student st = new Student();
        st.EducationInfo();
        break;
    }
    default:
        MessageBox.Show("Not valid ...");
}

2
在 case 内声明变量时,请使用大括号进行说明。
int personType = 1;
switch (personType)
{
    case 1: 
   {
     ///
     break;
   }
    case 2: 
   {
     ///
     break;
    }
    case 3: 
   {
        ///
        break;
   }
    ...
}

0

范围并不奇怪。局部变量的作用域是从定义它的点到定义它的块的结尾。因此,各种emp变量的作用域都延伸到以switch语句后的{开始的块的结尾,并在相应的}处结束。case标签没有什么特别之处;它们不会改变变量的作用域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接