可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
If you really want noop, then this defines a nameless action that doesn't do anything, and then invokes it, causing nothing to happen:
((Action)(() => { }))();
回答2:
The standard empty statement/noop operation in c# is
;
as in:
if (true)
;
(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
回答3:
If you want to break into the method you could hardcode a breakpoint:
System.Diagnostics.Debugger.Break();
Alternatively if you don't compile in release mode, the following line will emit IL which you can break on:
var a = 1;
You could also write a Debug.Break() that is specific to your machine:
[Conditional("DEBUG")]
[Obsolete("Please remove me before checkin.")]
public static void Break()
{
#IF DEBUG
if (Dns.GetHostName() == "PROTECTORONE")
Debugger.Break();
#ENDIF
}
Note that because of [Conditional("DEBUG")]
that method will not get called in call sites during a RELEASE build.
回答4:
You can write a function that does nothing.
public static void Noop()
{
}
回答5:
You can just write:
catch {
;
}
The empty statement with a single semicolon is the C# NOOP.
回答6:
How about:
GC.KeepAlive(e);
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
:
"".AsEnumerable();
回答7:
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 the catch
block.
回答8:
Why over-engineer this?
var x = 0;
works just fine :)
回答9:
The standard empty statement/noop operation in C# is ;
as in if (true) ;
.
- blueberryfields
But using that standard ;
as a branch of an if
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:
if (condition1)
action1;
else if (condition2)
; // (do nothing)
else if (condition3)
action3;
else if (condition4)
; // (do nothing)
else if (condition5)
action5;
else
action99;
(I lamented being unable to write this as a comment because I did not yet "have 50 reputation to comment". Now that I can comment, at 2K bytes, it is too long for a comment by 1.5K bytes, so it's staying here.)
回答10:
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
catch(Exception exception)
{
}
and put the breakpoint on the closing bracket and see the exception content.
回答11:
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.
.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
}
If you compile the application, and decompile it with a tool like ILSpy, to C#, this is the contents of the main() method:
static void main()
{
}
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:
.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 is certainly compiling the nop
instructions into the assembly. Since C# has no implementation of this instruction, these nop
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#.
回答12:
Are you trying to debug a release (optimised) build? It is normally the optimiser that removes unreferenced variables and empty blocks.
Two solutions:
- Debug in a debug build.
- Put a break point on the
catch
itself and use $exception
– created by the debugger to reference the exception in flight – in the Locals tool window.
回答13:
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
((Action)(() => { }))();
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)
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>noop</Title>
<Shortcut>noop</Shortcut>
<Description>Code snippet to inject an assembly (x86) equivalent of the NOOP command into the code's disassembly.</Description>
<Author>Jay Whaley</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Code Language="csharp">
<![CDATA[// Forces a psuedo NOOP in disassembly
((Action)(() => { }))();
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
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#.
回答14:
Reliable solution
try
{
blablablablaStatemnt();
}
catch(Exception ex)
{
#IF DEBUG
Debugger.Break();
#END IF
}
As simple as this!
Otherwise
breakpoints
can be very usefull;
回答15:
I quite like this, just because it will confuse whoever comes across it:
catch (SomeException e)
{
lock(e);
}