简单的 C# Noop 语句
C# 中不需要实现方法的简单 Noop 语句是什么? (不过,内联/Lambda 方法是可以的。)
我当前的用例:我想占用 try-catch 的 catch 块,这样我就可以在调试时进入它并检查异常。
我知道无论如何我应该处理/记录异常,但这不是本练习的重点。
What is a simple Noop statement in C#, that doesn't require implementing a method?
(Inline/Lambda methods are OK, though.)
My current use case: I want to occupy the catch-block of a try-catch, so I can step into it while debugging and inspect the exception.
I'm aware I should probably be handling/logging the exception anyway, but that's not the point of this exercise.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
C#中标准的空语句/noop操作如下
:(
相关文档)
这专门解决了您的用例(只需在 ; 行上放置一个断点,或以其他方式单步执行),是最小的,并且为此目的而直接受到环境支持(因此您即使你正在做复杂的事情,比如查看编译的源代码,你不会有任何额外的噪音/等等,需要担心编译器/优化器/等等...) - 并且有额外的好处警告,提醒您在完成调试/推送到生产环境后将其从代码中清除
The standard empty statement/noop operation in c# is
as in:
(relevant documentation)
this specifically addresses your use case (just place a break-point on the ; line, or otherwise step to it), is minimal, and is directly supported by the environment just for this purpose (so you even if you're doing complex things, like looking at the compiled source, you won't have any additional noise/etc.. to worry about from the compiler/optimizer/etc...) - and has the additional benefit of putting up a warning, as a reminder to clean it out of your code when you're done debugging/push to production
如果你真的想要 noop,那么这定义了一个不执行任何操作的无名操作,然后调用它,导致什么也不会发生:
If you really want noop, then this defines a nameless action that doesn't do anything, and then invokes it, causing nothing to happen:
如果你想闯入该方法,你可以硬编码一个断点:
或者,如果你不在发布模式下编译,下面的行将发出你可以中断的IL:
你也可以编写一个特定的 Debug.Break()到您的计算机:
请注意,由于
[Conditional("DEBUG")]
,该方法不会在 RELEASE 构建期间在调用站点中被调用。If you want to break into the method you could hardcode a breakpoint:
Alternatively if you don't compile in release mode, the following line will emit IL which you can break on:
You could also write a Debug.Break() that is specific to your machine:
Note that because of
[Conditional("DEBUG")]
that method will not get called in call sites during a RELEASE build.But 使用标准
;
作为if
语句的分支会使 MS Visual Studio 2010 显示警告:“可能错误的空语句” 。 (警告 CS0642,尽管 VS2010 没有告诉我这一点,也没有链接到该警告的实际帮助。)更糟糕的是,MSDN C# 语言规范没有提到实际上编码空语句作为
if
语句的分支会引发警告 CS0642“可能错误的空语句”。 (警告因为它是“坏形式”,可能不明确。)更糟糕的是,看起来 VS2010 没有提供完全抑制单个警告的方法。我必须在行之前插入
#pragma warning disable CS0642
,并在行之后插入[可选]#pragma warning disable CS0642
。对我来说,这比警告更丑陋。我最好使用{ }
代替;
。 (我可能会使用一个不太难看的覆盖。)我在这里查找“C# no-op”,因为我想要“空语句”的替代方案,以消除该警告。我不需要检查站。我只想做一个[绝对]什么都不做的事情,不像“空声明”那样含糊不清。
替代方案不得引起其他警告。
int u;
不好,因为它会引发警告“变量'u'已声明但从未使用”。int u = 0;
不好,因为它会引发警告“变量 'u' 已被赋值,但其值从未被使用”。如果将
noop;
(或类似的)添加为明确的空语句(不是宏定义),那就太好了。如果
noop();
(或类似)是一个具有空函数体的函数(当编译器内联它时,它可以完全消失),那就太好了。当分支只有一个语句时,我经常省略周围的
{
和}
行,因为它们不是必需的,而且它们垂直拉伸代码,使其更难以阅读。该语言的不一致之处在于,当周围的{
和}
行包围 ZERO 语句时,我无法省略它们。我可以将这两行压缩为同一行上的{ }
,但这是不一致的。我认为;
一行是最简洁的解决方案,它不应该因“不良形式”的[未声明]理由而引起警告。我认为警告 CS0642 应该默认为关闭。我认为以下代码应该可以接受:But using that standard
;
as a branch of anif
statement makes MS Visual Studio 2010 show a Warning: "Possible mistaken empty statement". (Warning CS0642, though VS2010 doesn't tell me that or link to actual help for the warning.)Worse, the MSDN C# Language Specification does not mention that actually coding that empty statement as a branch of an
if
statement provokes Warning CS0642 "Possible mistaken empty statement". (Warning because it is "bad form", potentially ambiguous.)Worse yet, it looks like VS2010 provides no way to NEATLY suppress an individual warning. I would have to insert
#pragma warning disable CS0642
before the line(s) and [optionally]#pragma warning disable CS0642
after. To me, this is uglier than the warning. I'd be better off using{ }
in place of;
. (I might use an override that is a little less ugly.)I looked here for a "C# no-op" because I wanted an alternative to the "empty statement", to get rid of that warning. I don't need a checkpoint. I just want a do-[absolutely]-nothing that is not ambiguous like "the empty statement".
The alternative must not provoke SOME OTHER warning.
int u;
is no good because it provokes Warning "The variable 'u' is declared but never used".int u = 0;
is no good because it provokes Warning "The variable 'u' is assigned but its value is never used".If
noop;
(or similar) were added as an unambiguous empty statement (NOT a macro definition), that would be great.If
noop();
(or similar) were a function with an empty body (which can disappear completely when the compiler inlines it), that would almost be great.When the branch is only one statement, I often omit the surrounding
{
and}
LINES because they are not needed and they stretch the code vertically, making it harder to read. The inconsistency in the language is that I can't omit the the surrounding{
and}
LINES when they surround ZERO statements. I can compact the two lines to{ }
on the same line, but that is inconsistent. I think;
on a line is the neatest solution, and it should NOT cause a warning on the [unstated] grounds of "bad form". I think warning CS0642 should have defaulted to OFF. I think the following code should be acceptable as-is:您可以编写一个不执行任何操作的函数。
You can write a function that does nothing.
你可以这样写:
带有一个分号的空语句是C# NOOP。
You can just write:
The empty statement with a single semicolon is the C# NOOP.
我知道这是一个老问题,从技术上讲,这个答案与提问者的用例无关。不过,CIL中有一条NOOP指令,即
nop
。作为实验,采用以下 CIL 应用程序。如果您编译该应用程序,并使用 ILSpy 等工具将其反编译为 C#,则这就是 main() 方法的内容:
如您所见,那里什么也没有。但是,如果我们想验证 CIL 编译器没有优化这些 nop 语句,我们可以在 ILSpy 中查看反编译的 IL 代码中的应用程序,这就是我们在 main 方法中看到的内容:
CIL 肯定会将
nop
指令编译到程序集中。由于 C# 没有此指令的实现,因此这些nop
命令不会显示在反汇编的 C# 代码中。我没有 Reflector 的许可证,但我想如果您使用 Reflector 反编译这些二进制文件,您会得到类似的 C# 输出。
I know this is an old question and, technically, this answer doesn't relate to the asker's use case. However, there is a NOOP instruction in CIL, which is
nop
. As an experiment, take the following CIL application.If you compile the application, and decompile it with a tool like ILSpy, to C#, this is the contents of the main() method:
As you can see, there is nothing there. However, if we want to verify that the CIL compiler didn't optimize out these
nop
statements, we can view our application in decompiled IL code in ILSpy, and this is what we see for the main method:CIL is certainly compiling the
nop
instructions into the assembly. Since C# has no implementation of this instruction, thesenop
commands are not shown within the disassembled C# code.I don't have a license for Reflector but I imagine if you decompile these binaries with Reflector you would get similar output for C#.
怎么样:
其中
e
是异常变量?(我还没有尝试在 catch 声明本身上设置断点。感觉你应该能够做到这一点,正是因为这个原因。但是它是否有效是另一回事.)
或者更神秘一点,假设您已经有了
System.LINQ
的 using 指令:How about:
where
e
is the exception variable?(I haven't tried putting a break point on the catch declaration itself. It feels like you ought to be able to do that, precisely for this reason. But whether it works or not is a different matter.)
Or somewhat more cryptically, assuming you've already got a using directive for
System.LINQ
:除了直接回答问题的答案之外。
如果您只想中断,那么您可以随时将断点放在
catch
块的开始{
或结束}
上。In addition to the answers that directly answer the question.
If you just want to break, then you could always put the breakpoint on the opening
{
or closing}
of thecatch
block.在考虑了各种选项之后,我认为一对空括号和简洁的注释是最干净的。没有额外的代码,自记录,并且比单个分号明显得多。
例如
After considering various options I decided that a pair of empty brackets and a terse comment were cleanest. No extra code, self-documenting, and far more obvious than a single semicolon.
e.g.
很多很棒的解决方案!我的做法是:
当您想要确认有返回值,但您不想要或不需要它时,使用 _ 。它可以让编译器安静下来,避免告诉您没有获得返回值。
Lots of great solutions! My go to is:
_ is used when you want to acknowledge there is a return value, but you don't want or need it. It can quiet the compiler from telling you aren't getting the return value.
那么 C# 中的 NOP 存在,就像在 C 中一样,是
';'
,其正确定义是“空语句”,但对于您想要的用法来说,足以将断点放在结束 catch 括号中...无需保持活动状态,因为当附加调试器时,方法中对象引用的生命周期将延长到方法的末尾。因此,您只需编写
并将断点放在右括号上即可查看异常内容。
Well the NOP in C# exists, as in C and is
';'
and its correct definition is "the empty statement", but for the usage you intend, is enought to put the breakpoint in the closing catch bracket...There is no needing to Keep Alive anithing, since Tthe lifetime of an object reference in a method is extended to the end of the method when the debugger is attached. So you simply need to write
and put the breakpoint on the closing bracket and see the exception content.
您是否正在尝试调试发布(优化)版本?通常是优化器删除未引用的变量和空块。
两种解决方案:
catch
本身上放置一个断点,并在 Locals 工具窗口中使用$exception
(由调试器创建以引用运行中的异常)。Are you trying to debug a release (optimised) build? It is normally the optimiser that removes unreferenced variables and empty blocks.
Two solutions:
catch
itself and use$exception
– created by the debugger to reference the exception in flight – in the Locals tool window.为什么要过度设计这个?
工作得很好:)
Why over-engineer this?
works just fine :)
这是对 @AHM 答案的补充,因为我想要一种简单的方法来执行 NOOP 以便进行调试(与 AB PLC CompactLogix 通信,并且由于 C# 中的 C++ 库 DLL 导入而遇到仅在反汇编中真正可见的错误)。
我将单行代码
放入名为 noop.snippet 的代码片段中,然后将其放入名为“我的代码片段”的文件夹中。
(工具 -> 代码片段管理器 -> 位置)或和弦(Ctrl+K、Ctrl+B)
这有助于使其成为快速使用的快捷方式,以防万一级别的通信变得混乱,需要这是一种常见的调试策略。生成的实际程序集如下,但有 一些关于如何在 C# 中内联使用实际汇编。
This is an addition to @AHM 's answer since I wanted an easy way to do NOOP for debugging purposes (communicating with AB PLC CompactLogix and ran into errors only really visible in Disassembly because of C++ library DLL import in C#).
I took the one-liner
and put it into a snippet named noop.snippet then placed it in the folder named My Code Snippets.
(Tools -> Code Snippets Manager -> Location) OR Chord (Ctrl+K,Ctrl+B)
This helps to make it a quick use shortcut in case low level communication becomes muddled and requires this to be a common debugging tactic. The actual assembly generated is as follows, but there're some posts about how to use actual assembly inline in C#.
可靠的解决方案
就这么简单!
否则
断点
会非常有用;
Reliable solution
As simple as this!
Otherwise
breakpoints
can be very usefull;
这就是我在为单元测试编写一些“Fakes”时所做的事情,并且某些方法将留空。
我按照智能感知提示得到了上述结果。我的环境是Visual Studio 2022
This is what I did when I was writing some "Fakes" for unit tests and some of the methods were to be left blank.
I followed the intellisense cues and got the above. My environment is Visual Studio 2022
我很喜欢这个,只是因为它会让遇到它的人感到困惑:
I quite like this, just because it will confuse whoever comes across it: