56

什么是 C# 中不需要实现方法的简单 Noop 语句?(不过,内联/Lambda 方法是可以的。)

我当前的用例:我想占用 try-catch 的 catch-block,所以我可以在调试时进入它并检查异常。
我知道无论如何我可能应该处理/记录异常,但这不是本练习的重点。

4

17 回答 17

76

如果你真的想要noop,那么这定义了一个不做任何事情的无名动作,然后调用它,没有任何事情发生:

((Action)(() => { }))();
于 2011-08-03T10:11:58.170 回答
74

c# 中的标准空语句/noop 操作是

;

如:

if (true)
    ;

相关文件

这专门针对您的用例(只需在 ; 行上放置一个断点,或以其他方式进入它),是最小的,并且仅出于此目的由环境直接支持(因此即使您正在做复杂的事情,就像查看已编译的源代码一样,您不会有任何额外的噪音/等..来自编译器/优化器/等...) - 并且具有发出警告的额外好处,以提醒您完成调试/推送到生产后,将其从代码中清除

于 2013-12-27T20:36:13.560 回答
17

如果你想闯入该方法,你可以硬编码一个断点:

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 构建期间不会在调用站点中被调用。

于 2011-08-03T10:12:26.317 回答
10

你可以编写一个什么都不做的函数。

public static void Noop()
{
}
于 2011-08-03T10:09:56.017 回答
9

C# 中的标准空语句/noop 操作;if (true) ;.
- 蓝莓园

但是使用该标准;作为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();(或类似的)是一个具有空主体的函数(当编译器内联它时它可以完全消失),那几乎是很棒的。

当分支只有一个语句时,我经常省略周围{}LINES,因为它们不需要它们并且它们垂直拉伸代码,使其更难阅读。语言中的不一致之处在于,当它们围绕 ZERO 语句时,我不能省略环绕{}LINES。我可以将两条线压缩到{ }同一条线上,但这是不一致的。我认为;在线是最简洁的解决方案,它不应该以[未说明的]“不良形式”为由发出警告。我认为警告 CS0642 应该默认为 OFF。我认为以下代码应该是可以接受的:

if (condition1)
  action1;
else if (condition2)
  ;  // (do nothing)
else if (condition3)
  action3;
else if (condition4)
  ;  // (do nothing)
else if (condition5)
  action5;
else
  action99;

(我很遗憾无法将其写为评论,因为我还没有“有 50 个声望来评论”。现在我可以评论了,2K 字节,1.5K 字节的评论太长了,所以它留在这里.)

于 2016-06-26T04:06:30.063 回答
7

You can just write:

catch {
    ;
}

The empty statement with a single semicolon is the C# NOOP.

于 2013-05-09T10:38:58.433 回答
6

怎么样:

GC.KeepAlive(e);

e异常变量在哪里?

(我没有尝试在 catch 声明本身上设置断点。感觉你应该能够这样做,正是因为这个原因。但它是否有效是另一回事。)

或者更神秘一点,假设你已经有了一个 using 指令System.LINQ

"".AsEnumerable();
于 2011-08-03T10:08:37.817 回答
5

除了直接回答问题的答案。


如果你只是想中断,那么你总是可以将断点放在块的打开{或关闭}catch

于 2011-08-03T10:14:21.173 回答
5

我知道这是一个老问题,从技术上讲,这个答案与提问者的用例无关。但是,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
}

如果您编译应用程序,并使用 ILSpy 等工具将其反编译为 C#,则 main() 方法的内容如下:

static void main()
{
}

如您所见,那里什么都没有。但是,如果我们想验证 CIL 编译器没有优化这些nop语句,我们可以在 ILSpy 中以反编译的 IL 代码查看我们的应用程序,这就是我们在 main 方法中看到的:

.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# 没有实现此指令,因此这些nop命令未显示在反汇编的 C# 代码中。

我没有 Reflector 的许可证,但我想如果你用 Reflector 反编译这些二进制文件,你会得到类似的 C# 输出。

于 2015-01-21T14:00:13.700 回答
4

为什么过度设计这个?

var x = 0;

工作得很好:)

于 2011-09-15T15:01:47.397 回答
3

那么 C# 中的 NOP 存在,就像在 C 中一样';',它的正确定义是“空语句”,但是对于您想要的用法,足以将断点放在关闭的 catch 括号中......没有必要保留还活着,因为当附加调试器时,方法中对象引用的生命周期会延长到方法的末尾。所以你只需要写

catch(Exception exception)
{
}

并将断点放在右括号上并查看异常内容。

于 2011-08-03T10:16:39.030 回答
3

您是否正在尝试调试发布(优化)版本?通常是优化器删除未引用的变量和空块。

两种解决方案:

  • 在调试版本中进行调试。
  • 在自身上放置一个断点catch并使用$exception——由调试器创建以引用飞行中的异常——在 Locals 工具窗口中。
于 2011-08-03T10:31:54.237 回答
1

这是@AHM 答案的补充,因为我想要一种简单的方法来执行 NOOP 以进行调试(与 AB PLC CompactLogix 通信并遇到错误,因为 C# 中的 C++ 库 DLL 导入,只有在反汇编中才真正可见)。

我拿了单线

((Action)(() => { }))();

并将其放入名为noop.snippet的片段中,然后将其放入名为 My Code Snippets 的文件夹中。
工具 -> 代码片段管理器 -> 位置)或和弦(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>

这有助于使其成为一种快速使用的快捷方式,以防低级通信变得混乱,并要求这是一种常见的调试策略。实际生成的程序集如下,但是有一些帖子是关于如何在 C#中使用实际的程序集内联。

调用无名操作生成的反汇编

于 2019-01-30T19:31:21.403 回答
1

在考虑了各种选项后,我决定一对空括号和一个简洁的注释是最干净的。没有额外的代码,自我记录,并且比单个分号更明显。

{/* Noop */}

例如

if (String.IsNullOrEmpty(value))
    {/* Noop */}
else if (Data.ContainsKey(key))
于 2021-08-30T23:35:02.910 回答
0

可靠的解决方案

try
{
   blablablablaStatemnt();
}
catch(Exception ex)
{
    #IF DEBUG
       Debugger.Break();
    #END IF
}

就这么简单!

否则

断点

可能非常有用;

于 2017-07-19T08:59:22.323 回答
0

很多很棒的解决方案!我的目标是:

_ = "";
于 2021-09-19T13:51:36.947 回答
-2

我很喜欢这个,只是因为它会让遇到它的人感到困惑:

catch (SomeException e)
{
    lock(e);
} 
于 2011-08-03T10:32:51.590 回答