C#中的案例声明块级声明空间

有没有理由我错过了case语句中的块不被视为块级声明空间?

我尝试时不断收到错误(变量已经声明)

case x: var someVariable = 42; break; case y: var someVariable = 40; break; 

但我能做到

 case x: try{var someVariable = 42;}catch{} break; case y: try{var someVariable = 40;}catch{} break; 

如果C#允许通过语句,那就没有意义,但事实并非如此,我想不出你可以在case语句中声明变量并在该块之外使用它的场景。

更新:这个问题被用作这篇博文的灵感来源; 看到它的更多细节。

http://ericlippert.com/2009/08/13/four-switch-oddities/

感谢有趣的问题。


在其他各种答案中存在许多混淆和错误陈述,其中没有一个真正解释了为什么这是非法的。 我将尝试确定。

首先,要严格正确,“范围”是用来描述问题的错误词。 巧合的是,我上周写了一篇关于“范围”错误使用的博客文章; 这将在我的迭代器块系列之后发布,它将在整个7月份运行。

正确使用的术语是“ 声明空间 ”。 声明空间是一个代码区域,其中不能声明两个不同的东西具有相同的名称 。 这里描述的场景是交换器部分没有定义声明空间这一事实的症状,尽管交换机确实如此。 由于OP的两个声明属于同一个声明空间并且具有相同的名称,因此它们是非法的。

(是的,switch块定义了一个范围,但这个事实与问题无关,因为问题是关于声明合法性 ,而不是标识符查找语义 。)

一个合理的问题是“为什么这不合法?” 一个合理的答案是“好吧,为什么要这样”? 你可以用两种方式之一。 这是合法的:

 switch(y) { case 1: int x = 123; ... break; case 2: int x = 456; ... break; } 

或者这是合法的:

 switch(y) { case 1: int x = 123; ... break; case 2: x = 456; ... break; } 

但你不可能两种方式。 C#的设计者选择第二种方式似乎是更自然的方式。

这个决定是在1999年7月7日做出的,差不多十年前。 当天笔记中的评论非常简短,只是简单地说明“ 开关案例不会创建自己的声明空间 ”,然后提供一些示例代码,说明哪些有效,哪些无效。

为了更多地了解这个特定日子里设计师的想法,我不得不让很多人对他们十年前所想的事情感到不满 – 而且还要告诉他们什么是最终的微不足道的问题; 我不打算这样做。

简而言之,没有特别令人信服的理由选择这样或那样的方式; 两者都有优点。 语言设计团队选择了一种方式,因为他们必须选择一种方式; 他们选择的那个对我来说似乎很合理。

啊 – 你没有摔倒,但是你可以使用goto跳转到另一个标记的case块。 因此,块必须在相同的范围内。

你也可以这样做:

 case x: {var someVariable = 42;} break; case y: {var someVariable = 40;} break; 

本质上,大括号创建词法范围,因此没有大括号,someVariable会被加载到符号表中两次。 我认为这种选择可能只是为了避免混淆,并可能避免增加符号表构建的复杂性。

因为大小写不是块,所以没有花括号表示范围。 由于缺乏更好的词,例如标签。

你最好在switch()语句之外声明变量并在之后使用它。 当然,在这种情况下,您将无法使用var关键字,因为编译器将不知道要初始化的类型。

您可以在switch语句的范围之外声明变量。

 var someVariable; switch(); case x: someVariable = 42; break; case y: someVariable = 40; break;