Luk*_* Vo 5 c# grammar using-statement switch-statement
考虑以下代码:
switch ("")
{
case "":
using var s = new MemoryStream();
break;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不会编译并显示以下错误:“A using 变量不能直接在 switch 部分中使用(考虑使用大括号)”。
修复已经在建议中,但我的问题是为什么下面的代码是合法的,但上面的代码不是?为什么 C# 不能只允许前面的代码?
switch ("")
{
case "":
{
using var s = new MemoryStream();
}
// break can be inside or outside the braces
break;
}
Run Code Online (Sandbox Code Playgroud)
C# 8.0 对新using语句的语言提案给出了这样的解释:
由于其实际生命周期的复杂性,直接在标签内声明
using是非法的。case一种可能的解决方案是简单地赋予它与out var同一位置的 相同的生命周期。人们认为功能实现的额外复杂性和解决方法的简便性(只需在标签上添加一个块case)并不能证明采取这条路线是合理的。
举个例子,考虑一下这......
switch( foo )
{
case 1: // Yeah, I'm in the tiny minority who believe `case` statements belong in the same column as the `switch` keyword.
case 2:
using FileStream fs1 = new FileStream( "foo.dat" );
goto case 4;
case 3:
using FileStream fs3 = new FileStream( "bar.dat" );
goto case 1;
case 4:
using FileStream fs4 = new FileStream( "baz.dat" );
if( GetRandomNumber() < 0.5 ) goto case 1;
else break;
}
Run Code Online (Sandbox Code Playgroud)
...相当于这个伪代码(忽略顺序if逻辑):
if( foo == 1 || foo == 2 ) goto case_1;
else if( foo == 3 ) goto case_3;
else if( foo == 4 ) goto case_4;
else goto after;
{
case_1:
using FileStream fs1 = new FileStream( "foo.dat" );
goto case_4;
case_3:
using FileStream fs3 = new FileStream( "bar.dat" );
goto case_1;
case_4:
using FileStream fs4 = new FileStream( "baz.dat" );
if( GetRandomNumber() < 0.5 ) goto case_1;
else goto after;
}
after:
Run Code Online (Sandbox Code Playgroud)
...规范说“与using在同一位置的语句中声明变量具有相同的效果。”,所以如果我正确理解规范,上面的代码将与此相同:
if( foo == 1 || foo == 2 ) goto case_1;
else if( foo == 3 ) goto case_3;
else if( foo == 4 ) goto case_4;
else goto after;
{
case_1:
using( FileStream fs1 = new FileStream( "foo.dat" ) )
{
goto case_4;
case_3:
using( FileStream fs3 = new FileStream( "bar.dat" ) )
{
goto case_1;
}
case_4:
using( FileStream fs4 = new FileStream( "baz.dat" ) )
{
if( GetRandomNumber() < 0.5 ) goto case_1;
else goto after;
}
}
}
after:
Run Code Online (Sandbox Code Playgroud)
我认为问题是:
case_4虽然从to 的跳转case_1是明确定义的 Causefs4的处置......fs1应该立即处理goto case_4(之后case_1:)fs3应该初始化,因为它在范围内(忽略它没有被使用的事实)。case_1:case_4:fs1应该在 incase 3和时初始化case 4,即使严格来说它在范围内。因为链接的规范提案仅显示向后 到块之前goto的点(因此该语句的主题将超出范围),而在这种情况下,它没有明确定义 if和仍在范围内(或不在范围内)向前跳跃时。usingusingfs1fs3
请记住,using;该对象应该在超出范围时被处置,而不是说它应该在其声明的范围内最后一次使用时被处置(这将禁止将其传递给仍在使用它的另一个方法)。
对于可能/应该发生的事情至少有两个论据:
fs1一旦跳转到,就立即处理case_3,即使从fs1技术上讲仍然在范围内(如果您订阅“所有案例共享相同范围”的思想流派)。
using;这也忽略了将其主题的生命周期严格绑定到封闭范围的语句的要点。fs1 仅当控制权离开整个块时才进行处置switch(即使可以说fs1在此之前超出了范围)。
正如提案中提到的,这是可以敲定的事情,但考虑到语言设计团队所面临的时间限制,人们可能不会同意这一点。
| 归档时间: |
|
| 查看次数: |
975 次 |
| 最近记录: |