12

コンパイルしたC#コードを読み込もうとしています。

これは私のコードです:

using(OleDbCommand insertCommand = new OleDbCommand("...", connection))
{
   // do super stuff
}

だが!

使用法がこれに変換されることは誰もが知っています:

{
    OleDbCommand insertCommand = new OleDbCommand("...", connection)
    try
    {
        //do super stuff
    }
    finally
    {
        if(insertCommand != null)
            ((IDisposable)insertCommand).Dispose();
    }
}

(OleDbCommandは参照型であるため)。

しかし、アセンブリ(.NET 2.0でコンパイル)を逆コンパイルすると、Resharperで次のようになります。

try
{
    insertCommand = new OleDbCommand("", connection);
Label_0017:
    try
    {
       //do super stuff
    }
    finally
    {
    Label_0111:
        if ((insertCommand == null) != null)
        {
            goto Label_0122;
        }
        insertCommand.Dispose();
    Label_0122:;
    }

私はこの行について話している:if ((insertCommand == null) != null)

insertCommandがnullだとしましょう。次に、最初の部分がtrueを返します。(true != null)を返しますtrue。それで、処分はまだスキップされますか?奇妙な、非常に奇妙な。

これをVisualStudioに貼り付けると、Resharperはすでに警告しています:式は常にtrueです...

ありがとう!

-クリストフ

4

2 に答える 2

12

デコンパイラにはバグがあります。この行

if ((insertCommand == null) != null) 

に逆コンパイルされている必要があります

if ((insertCommand == null) != false)

これは不必要に冗長ですが、少なくとも正しいコードです。

C#コンパイラは頻繁に出力することを選択するため、デコンパイラはおそらくこの不必要に冗長なバージョンを実行します

if (x)
   Y();
Z();

あなたが書いたかのように

if (!x)
    goto L;
Y();
L: Z();

両方のプログラムに対して生成されたコードは同じであるため、逆コンパイラーは、どちらが表示するのがより適切なコードであるかを常に認識しているわけではありません。

予期しない「!= false」の理由は、何かが真であるかどうかをテストするILを生成するときに、生成できる最も高速でコンパクトなコードが、それが偽でないかどうかをテストするためです。FalseはILでゼロとして表され、「これはゼロですか?」という安価な指示があります。

于 2010-05-07T14:15:51.203 に答える
0

コードを逆コンパイルしても、元のコードに戻る保証はありません。.netコードがILにコンパイルされると、最適化されます。アプリケーションがILをC#に変換し直すと、気が狂うことがあります。これは、コードが機能しないことを意味するのではなく、アプリケーション(この場合はリシャーパー)がILを変換した方法です。

あなたがそれについて心配しているなら、私はそれが何にコンパイルされたかを見るためにILを直接見るでしょう。

補足:ILをC#またはVB.netに逆コンパイルしても、コンパイルが保証されるわけではありません。:)

試してみるもう1つの製品はReflectorです

于 2010-05-07T13:54:06.553 に答える