在C#中,什么是简单的Noop语句,它不需要实现一个方法?(内联/lambda方法可行)
我的当前用例:我想占用try-catch的catch块,以便在调试时可以进入该块并检查异常。
我知道我应该处理/记录异常,但这不是本练习的重点。
C# 中的标准空语句/空操作是
;
就像这样:
if (true)
;
(相关文档)
这个方法非常适合您的使用情况(只需在 ; 行上设置断点,或者以其他方式执行到该行),它是最简化的,并且环境直接支持此目的(因此即使您正在进行复杂的操作,比如查看编译后的源代码,您也不必担心编译器/优化器等会引入其他噪音等)- 并且还具有额外的好处,即发出警告,提醒您在完成调试/推送到生产之后将其从代码中删除。
// NOOP
,以便让别人知道这是有意为之的。 - gfache;
只会被编译器忽略,所以从行为上来看它不是一个空操作。它应该什么都不做,而不是什么都不存在。 - Protector onefor (int i = 0; i < 2000000000; i++) ;
... 你会发现它会执行几秒钟。所以它不会被编译忽略掉。 - undefined如果您真的想要“noop”,那么这将定义一个没有名称的动作,它不执行任何操作,然后调用它,导致什么也不发生:
((Action)(() => { }))();
如果你想进入该方法,你可以硬编码一个断点:
System.Diagnostics.Debugger.Break();
如果您不使用发布模式进行编译,以下代码行将会生成 IL 代码,您可以在其上设置断点:
var a = 1;
您还可以编写针对您的计算机特定的Debug.Break():
[Conditional("DEBUG")]
[Obsolete("Please remove me before checkin.")]
public static void Break()
{
#IF DEBUG
if (Dns.GetHostName() == "PROTECTORONE")
Debugger.Break();
#ENDIF
}
请注意,由于 [Conditional("DEBUG")]
,该方法在 RELEASE 构建期间的调用站点将不会被调用。
Debugger.Break
对于我的使用情况来说还不错,但如果它被意外提交了,我更希望有一些不会让人感到烦恼的东西。 - Protector one你可以编写一个不执行任何操作的函数。
public static void Noop()
{
}
;
,例如if (true) ;
。但是,如果将该标准;
作为if
语句的分支使用,则MS Visual Studio 2010会显示警告:“可能是错误的空语句”(警告CS0642,尽管VS2010没有告诉我或链接到实际的警告帮助)。更糟糕的是,MSDN C#语言规范并未提到将空语句作为if
语句的分支进行编码会引发警告CS0642“可能是错误的空语句”(警告因为它是“不好的形式”,潜在地模棱两可)。#pragma warning disable CS0642
,并在之后[可选]插入#pragma warning disable CS0642
。对我来说,这比警告本身还要丑陋。我最好使用{ }
代替;
。(我可能会使用一个稍微不那么丑陋的覆盖。)int u;
不行,因为它会引发警告“变量'u'已声明但从未使用”。int u = 0;
不行,因为它会引发警告“变量'u'被赋值,但其值从未使用”。noop;
(或类似的内容)作为空语句(而不是宏定义),那就太好了。noop();
(或类似的函数)是一个空体的函数(当编译器内联时可以完全消失),那将几乎是很好的。{
和}
行,因为它们是不必要的,并且会使代码在垂直方向上拉伸,使其更难阅读。语言中的不一致性在于,当它们包围零个语句时,我不能省略周围的{
和}
行。我可以将这两行压缩成同一行上的{ }
,但这是不一致的。我认为在一行上使用;
是最整洁的解决方案,并且它不应该因“不良形式”的[未声明]理由而引发警告。我认为警告CS0642应默认关闭。我认为以下代码应该被接受:if (condition1)
action1;
else if (condition2)
; // (do nothing)
else if (condition3)
action3;
else if (condition4)
; // (do nothing)
else if (condition5)
action5;
else
action99;
catch {
;
}
GC.KeepAlive(e);
在这里,e
是异常变量?
(我尚未尝试在 catch 声明本身上设置断点。感觉应该可以做到,就是为了这个原因。但它是否有效是另一回事。)
或者更加含蓄地说,假设您已经针对 System.LINQ
有了 using 指令:
"".AsEnumerable();
GC.KeepAlive
非常适合这个要求。 - Jon Skeet除了直接回答问题的答案外。
如果您只是想要中断,那么您可以将断点放置在catch
块的开头{
或结尾}
处。
{
大括号。我可以在空的 catch 块中看到异常。当然,你需要写 catch(Exception e)
,并接受未使用的警告。 - H H我知道这是一个老问题,技术上说,这个答案与提问者的用例无关。然而,在CIL中有一个NOOP指令,即nop
。作为一个实验,可以参考下面的CIL应用程序。
.assembly extern mscorlib {}
.assembly Test
{
.ver 1:0:1:0
}
.module test.exe
.method static void main() cil managed
{
.maxstack 1
.entrypoint
nop
nop
nop
nop
ret
}
static void main()
{
}
正如您所看到的,这里什么也没有。然而,如果我们想要验证CIL编译器没有优化掉这些nop
语句,我们可以在ILSpy中查看我们的应用程序反编译后的IL代码,这是主方法的内容:
.method static privatescope
void main$PST06000001 () cil managed
{
// Method begins at RVA 0x2050
// Code size 5 (0x5)
.maxstack 1
.entrypoint
IL_0000: nop
IL_0001: nop
IL_0002: nop
IL_0003: nop
IL_0004: ret
} // end of method '<Module>'::main
CIL会将nop
指令编译成汇编代码。由于C#没有实现这个指令,所以在反汇编的C#代码中不会显示这些nop
命令。
我没有Reflector的许可证,但我想如果你用Reflector反编译这些二进制文件,你会得到类似的C#输出。
在考虑了各种选项后,我决定使用一对空括号和一个简短的注释。没有多余的代码,自我说明,并且比单个分号更加明显。
{/* Noop */}
e.g.
if (String.IsNullOrEmpty(value))
{/* Noop */}
else if (Data.ContainsKey(key))
}
上? - George Duckettcatch (...)
处打断点并单步执行。 - porges}
的边缘。你可以尝试使用catch (Exception e) {{{{{{{{{{ }}}}}}}}}}
来更紧密地控制。 - porgescatch (Exception e) {}
会被简化为catch {}
。 - Jonathan Dickinson