メソッドが静的になる可能性があるのにReSharperが文句を言うのはなぜですか?
静的メソッドのインスタンスが(型上で)1つだけ作成され、パフォーマンスが節約されるためですか?
このコメントは、2つの重要なことを指摘しているため、非常に役立ちます。
問題のメソッドが実際にタイプの一部である必要があるかどうかを自問します。インスタンスデータを使用しないため、少なくとも独自のタイプに移動できるかどうかを検討する必要があります。それはタイプの不可欠な部分ですか、それとも本当に汎用のユーティリティメソッドですか?
メソッドを特定の型に保持することが理にかなっている場合は、コンパイラーが静的メソッドに対して異なるコードを発行するため、パフォーマンスが向上する可能性があります。
同じ警告のFxCopドキュメントから(強調を追加):
「インスタンスデータにアクセスしない、またはインスタンスメソッドを呼び出さないメンバーは、静的としてマークできます(Visual Basicで共有)。メソッドを静的としてマークすると、コンパイラはこれらのメンバーに非仮想呼び出しサイトを発行します。非仮想呼び出しを発行します。サイトは、現在のオブジェクトポインタがnullでないことを確認する各呼び出しの実行時のチェックを防ぎます。これにより、パフォーマンスに敏感なコードのパフォーマンスが測定可能に向上する可能性があります。場合によっては、現在のオブジェクトへのアクセスに失敗します。オブジェクトインスタンスは正確性の問題を表します。 "
ここでその主題に関する非常に良い議論(SO) 。私はif-it-can-be-made-static-make-it-staticの陣営にいます。これは、インスタンスデータを使用しないインスタンスメソッドがある理由の概念によるものだと思います。その場合、それは本当にインスタンスメソッドですか、それとも実際にはクラスメソッドですか?
静的として宣言されている場合、メソッドを使用するためにクラスの(ゼロ)インスタンスを作成する必要はありません...これにより、ガベージコレクターがオブジェクトを再利用する際に、構築処理、ヒープスペース、およびcpuサイクルに必要なcpuサイクルを節約できます。ヒープ...
また、あなたの質問は、それが書いたように
"...静的メソッドのインスタンスが1つだけ作成されます(タイプ上)..."
インスタンスメソッドの場合、メソッドのコードは、作成されたクラスのインスタンスごとに繰り返されることを意味します。それは真実ではありません。任意のタイプに対して作成するインスタンスの数に関係なく、メソッドのコードは1回だけメモリにロードされます。各インスタンスのヒープに格納されているオブジェクトは、タイプの「状態」(非静的フィールドといくつかのその他の追跡変数)のみを格納します。
それは苦情ではなく、単なるアドバイスです。
静的メソッドの場合、「this」を関数のスタックにプッシュする必要はありません。それが安いもう一つの理由です。
私にとって、このReSharperアドバイスの最大の利点(警告、提案、またはヒントとして設定できます)。それは私ができるだけ多くのメソッドを静的にすることを奨励しているということです。静的メソッドは、それがメンバーであるクラスに直接依存しないため、これは良いことです。これは、静的メンバーとして別のクラスに簡単に移動できることを意味します。
ReSharperの静的に関するもう1つの巧妙なトリックは、「メソッドを静的にする」リファクタリングを使用して、関連するメソッドのセットを静的にすることです。これにより、依存関係の一部がメソッドパラメータに移動します。後でこの一連のメソッドを見ると、すべてが特定のタイプの特定のオブジェクトにアクセスしていることがわかります。次に、「Makeメソッドを非静的」リファクタリングを使用して、そのオブジェクトを新しいthisポインターとして指定できます。これにより、メソッドが他のクラスに移動します。
これから:
internal class ClassA
{
public ClassB Property { get; set; }
public int Method()
{
var classB = Property;
return classB.Property1 + classB.Property2;
}
}
internal class ClassB
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
これに:
public static int Method(ClassB property)
{
var classB = property;
return classB.Property1 + classB.Property2;
}
これに:
internal class ClassA
{
public ClassB Property { get; set; }
}
internal class ClassB
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public int Method()
{
return Property1 + Property2;
}
}
スタティックは最初の使用時にインスタンス化され、メモリに残ります。使用しなくなった場合は問題の可能性があります。スタティックはテストが難しいです(モークなど...)。