メソッドの実装を必要としない、C#の単純なNoopステートメントとは何ですか?(ただし、インライン/ラムダメソッドはOKです。)
私の現在のユースケース:try-catchのcatch-blockを占有したいので、デバッグ中にステップインして例外を検査できます。
とにかく例外を処理/ログに記録する必要があることは承知していますが、それはこの演習のポイントではありません。
本当にnoopが必要な場合、これは何もしない名前のないアクションを定義し、それを呼び出して何も起こらないようにします。
((Action)(() => { }))();
C#での標準の空のステートメント/noop操作は
;
のように:
if (true)
;
(関連ドキュメント)
これは特にユースケースに対応し(;行にブレークポイントを配置するか、それ以外の場合はそれにステップします)、最小限であり、この目的のためだけに環境によって直接サポートされます(したがって、複雑なことをしている場合でも、コンパイルされたソースを見るのと同じように、コンパイラ/オプティマイザなどから心配する追加のノイズなどはありません...)-そして、警告を出すという追加の利点があります。デバッグ/本番環境へのプッシュが完了したら、コードからクリーンアップします
メソッドに侵入したい場合は、ブレークポイントをハードコーディングできます。
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ビルド中にコールサイトでメソッドが呼び出されないことに注意してください。
何もしない関数を書くことができます。
public static void Noop()
{
}
C#での標準の空のステートメント/ヌープ操作は
;
、のようになり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();
(または同様の)本体が空の関数(コンパイラがインライン化すると完全に消える可能性があります)の場合、それはほぼ素晴らしいことです。
ブランチが1つのステートメントしかない場合、周囲{
と}
LINESは不要であり、コードが垂直方向に引き伸ばされて読みにくくなるため、省略されることがよくあります。{
言語の不一致は、ZEROステートメントを囲むときに周囲と}
LINESを省略できないことです。2本の線を同じ線に圧縮することはできます{ }
が、それは一貫性がありません。私は;
、回線上が最も適切な解決策であると思います、そしてそれは「悪い形」の[述べられていない]理由で警告を引き起こすべきではありません。警告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バイトのコメントには長すぎるので、ここにとどまります。 。)
あなたはただ書くことができます:
catch {
;
}
セミコロンが1つある空のステートメントは、C#NOOPです。
どうですか:
GC.KeepAlive(e);
e
例外変数はどこにありますか?
(私はキャッチ宣言自体にブレークポイントを設定しようとはしていません。まさにこの理由から、それができるはずのように感じます。しかし、それが機能するかどうかは別の問題です。)
または、次のusingディレクティブがすでにあると仮定すると、もう少しわかりにくいですSystem.LINQ
。
"".AsEnumerable();
質問に直接答える答えに加えて。
ブレークしたいだけの場合は、いつでもブロックの開始{
または終了}
にブレークポイントを設定できます。catch
これは古い質問であり、技術的には、この回答は質問者のユースケースとは関係ありません。ただし、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コードでアプリケーションを表示できます。これは、メインメソッドで表示されるものです。
.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#でも同様の出力が得られると思います。
なぜこれをオーバーエンジニアリングするのですか?
var x = 0;
うまく動作します:)
C#のNOPは、Cと同様に存在し、';'
その正しい定義は「空のステートメント」ですが、意図する使用法では、ブレークポイントを閉じのキャッチブラケットに入れるのに十分です...保持する必要はありませんメソッド内のオブジェクト参照の存続期間は、デバッガーが接続されているときにメソッドの最後まで延長されるため、生きています。だからあなたは単に書く必要があります
catch(Exception exception)
{
}
ブレークポイントを閉じ括弧に入れて、例外の内容を確認します。
リリース(最適化)ビルドをデバッグしようとしていますか?通常、参照されていない変数と空のブロックを削除するのはオプティマイザーです。
2つの解決策:
catch
それ自体にブレークポイントを$exception
設定し、ローカルツールウィンドウで(実行中の例外を参照するためにデバッガーによって作成された)を使用します。デバッグ目的でNOOPを実行する簡単な方法が必要だったため、これは@AHMの回答への追加です(AB PLC CompactLogixと通信し、C#でのC ++ライブラリDLLのインポートが原因で、逆アセンブリでのみ実際に表示されるエラーが発生しました)。
ワンライナーを取りました
((Action)(() => { }))();
それをnoop.snippetという名前のスニペットに入れてから、 MyCodeSnippetsという名前のフォルダーに入れます。
([ツール]->[コードスニペットマネージャー]->[場所] )またはコード(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#で実際のアセンブリをインラインで使用する方法についての投稿がいくつかあります。
さまざまなオプションを検討した後、空の角かっこと簡潔なコメントのペアが最もクリーンであると判断しました。余分なコードや自己文書化はなく、単一のセミコロンよりもはるかに明白です。
{/* Noop */}
例えば
if (String.IsNullOrEmpty(value))
{/* Noop */}
else if (Data.ContainsKey(key))
信頼できるソリューション
try
{
blablablablaStatemnt();
}
catch(Exception ex)
{
#IF DEBUG
Debugger.Break();
#END IF
}
これと同じくらい簡単です!
さもないと
非常に便利です。
素晴らしいソリューションがたくさん!私の行き先は:
_ = "";
私はこれがとても好きです、なぜならそれはそれに出くわす人を混乱させるからです:
catch (SomeException e)
{
lock(e);
}