C# でメソッドへの参照の数をプログラム的に特定するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/106329

  •  01-07-2019
  •  | 
  •  

質問

最近、C# コンソール アプリケーションを継承しましたが、これには剪定とクリーンアップが必要です。簡単に言うと、このアプリは 110,000 行を超えるコードを含む 1 つのクラスで構成されています。そうです、1 つのクラスには 110,000 行以上あります。そしてもちろん、このアプリは私たちのビジネスの中核であり、24 時間稼働して動的な Web サイトで使用されるデータを更新します。私の前任者は「非常に優秀なプログラマ」だったそうですが、明らかに OOP (またはバージョン管理) にまったく興味がありませんでした。

ともかく...コードに慣れていくと、宣言されていても参照されていないメソッドがたくさんあることに気づきました。コードのバージョン管理にコピー/ペーストが使用されているように見えます。たとえば、getSomething important() というメソッドがあるとします。getSomethingImortant_April2007() という別のメソッドがある可能性があります (ほとんどの場合、パターンは functionName_[datestamp] です)。プログラマーが getSomethingMinimum() を変更するよう求められたとき、コピー/ペーストして getSomethingImortant_Date に名前を変更し、getSomethingImortant_Date に変更を加えてから、コード内のすべてのメソッド呼び出しを新しいメソッド名に変更して、古いメソッドをそのまま残しているようです。コードはありますが、参照されることはありません。

1 つの巨大なクラスをクロールし、すべてのメソッドのリストと各メソッドが参照された回数を返す単純なコンソール アプリを作成したいと考えています。私の推定によると、メソッドは 1000 をはるかに超えているため、これを手動で行うには時間がかかるでしょう。

このコードを調べるために使用できるクラスが .NET Framework 内にありますか?それとも、宣言されていても参照されていないメソッドを識別するのに役立つその他の便利なツールはありますか?

(余談:このような、非常に大きなクラスの C# アプリを見たことのある人は他にいますか?これは多かれ少なかれ 1 つの巨大な手続きプロセスであり、少なくともこの規模のものは初めて見たと思います。)

役に立ちましたか?

解決

使ってみてはいかがでしょうか N依存する クラスに関する統計を抽出する必要があるだけの場合。このツールは内部的に Mono.Cecil に依存してアセンブリを検査していることに注意してください。

他のヒント

ダウンロード 無料トライアル リシャーパーの。Resharper -> 検索 -> ファイル内の使用箇所を検索 (Ctrl-Shift-F7) を使用して、すべての使用箇所を強調表示します。また、ステータスバーにカウントが表示されます。複数のファイルを検索したい場合は、Ctrl-Alt-F7 を使用して検索することもできます。

それが気に入らない場合は、Visual Studio で関数名のテキスト検索 (Ctrl-Shift-F) を実行します。これにより、ソリューション内で見つかった関数の数と、それらがどこにあるかがわかります。

完了するには、 ロマン・ヴェルディエ 答えとして、ここで NDepend が何をもたらすのかを少し掘り下げてみましょう。(免責事項:私は NDepend チームの開発者です)

NDepend を使用すると、いくつかの LINQ クエリを使用して .NET コードをクエリできます。どのメソッドが呼び出され、どのメソッドによって呼び出されるかを知ることは、次の LINQ クエリを記述するだけで簡単です。

from m in Application.Methods
select new { m, m.MethodsCalled, m.MethodsCallingMe }

このクエリの結果は、呼び出し元と呼び出し先を簡単に参照できる方法で表示されます (Visual Studio に 100% 統合されています)。

NDepend methods callers and callees


役に立つ NDepend 機能が他にもたくさんあります。たとえば、次のことができます Visual Studio でメソッドを右クリック > NDepend > メソッドの選択...> 私を(直接的または間接的に)利用している人たち ...

NDepend Visual Studio method right click

次のコードクエリが生成されます...

from m in Methods 
let depth0 = m.DepthOfIsUsing("NUnit.Framework.Constraints.ConstraintExpression.Property(String)")
where depth0  >= 0 orderby depth0
select new { m, depth0 }

...これは、直接呼び出し元と間接呼び出し元を呼び出しの深さで照合します (1 は直接呼び出し元を意味し、2 は直接呼び出し元の呼び出し元を意味します)。

NDepend indirect method callers

そして、ボタンをクリックすると、 グラフにエクスポート, 、ピボット メソッドの呼び出しグラフを取得します (もちろんその逆、つまり特定のピボット メソッドによって直接または間接的に呼び出されるメソッド) の可能性があります。

NDepend call graph

これを自分で書きたいとは思わないので、購入してください N依存する そしてそれを使用してください コードクエリ言語

FXCop には、未使用のプライベート メソッドを識別するルールがあります。したがって、すべてのメソッドをプライベートとしてマークし、リストを生成させることができます。

もっと凝りたい場合は、FXCop にも言語がありますhttp://www.binarycoder.net/fxcop/

1 つのアセンブリに 1 つのクラスしか存在しないように聞こえるため、NDepend をシェルアウトしたくない場合は、メソッドをコメントアウトしてコンパイルします。コンパイルできたら、それらを削除します。継承や仮想メソッドなどの問題は発生しません。原始的に聞こえるかもしれませんが、リファクタリングはこのように単純な作業になる場合があります。これは、コードがクリーンアップされるまで (レッド/グリーン/リファクタリング)、各ビルド後に実行する単体テストがあることを前提としています。

アナライザーウィンドウ リフレクター メソッドが呼び出される場所 (使用者) を表示できます。
とはいえ、情報を得るまでにはかなりの時間がかかりそうです。
アドインを作成するために Reflector が提供する API を調べて、その方法で分析の面倒な作業を実行できるかどうかを確認してください。私は、ソースコードが コードメトリクスアドイン リフレクター API からメソッドに関する情報を取得する方法について少し説明します。

編集:また、 コードモデルビューア Reflector のアドインも役立ちます。これは、Reflector API を調べるのに良い方法です。

この特定のケースを処理するために構築されたものを私は知りませんが、Mono.Cecil を使用することはできます。アセンブリを反映してから、IL 内の参照をカウントします。厳しすぎてはいけません。

.NET Framework 自体には、これを行う簡単なツールはありません。ただし、未使用のメソッドを一度にリストする必要はないと思います。私が見たところ、コードを調べて、メソッドごとに未使用かどうかを確認し、未使用の場合は削除するだけです。これを行うには、Visual Studio の「参照の検索」コマンドを使用します。あるいは、Resharper の「分析」ウィンドウを使用することもできます。または、Visual Studio コード分析ツールを使用して、未使用のプライベート メソッドをすべて見つけることもできます。

.NET アセンブリではなく、x86 命令の場合と同様に、コンパイラーにアセンブラー ファイルを出力させるようにしてください。

なぜ?アセンブラー コードの解析は、C# コードや .NET アセンブリよりもはるかに簡単だからです。

たとえば、関数/メソッドの宣言は次のようになります。

    .string "w+"
    .text
    .type   create_secure_tmpfile, @function
create_secure_tmpfile:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    movl    $-1, -8(%ebp)
    subl    $4, %esp

関数/メソッドの参照は次のようになります。

    subl    $12, %esp
    pushl   24(%ebp)
    call    create_secure_tmpfile
    addl    $16, %esp
    movl    20(%ebp), %edx
    movl    %eax, (%edx)

「create_secure_tmpfile:」が表示されると、関数/メソッドの宣言があることがわかり、「call create_secure_tmpfile」が表示されると、関数/メソッドの参照があることがわかります。あなたの目的にはこれで十分かもしれませんが、そうでない場合は、あと数ステップでアプリケーション全体の非常にかわいいコール ツリーを生成できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top