静的にできる C#メソッドは静的でなければなりませんか?
今日私達はこれについて話し合っており、私は一種のフェンスの上にいます。数行をリファクタリングする長い方法があるとします。新しいメソッドは、おそらく親メソッドからいくつかのローカル変数を受け取り、値を返します。つまり、静的である可能性があります。
問題は、それは静的である必要がありますか?これは、設計や選択によって静的ではなく、インスタンス値を参照しないという性質上、単純です。
静的にできる C#メソッドは静的でなければなりませんか?
今日私達はこれについて話し合っており、私は一種のフェンスの上にいます。数行をリファクタリングする長い方法があるとします。新しいメソッドは、おそらく親メソッドからいくつかのローカル変数を受け取り、値を返します。つまり、静的である可能性があります。
問題は、それは静的である必要がありますか?これは、設計や選択によって静的ではなく、インスタンス値を参照しないという性質上、単純です。
回答:
場合によります。静的メソッドには実際に2つのタイプがあります。
小規模から中規模のコードベースでは、2つの方法を同じように扱うことができます。
最初のカテゴリ(静的にすることができる)にあるメソッドがあり、クラスの状態にアクセスするためにそれを変更する必要がある場合、静的メソッドをインスタンスメソッドに変換できるかどうかを判断するのは比較的簡単です。
ただし、大規模なコードベースでは、膨大な数の呼び出しサイトが、静的メソッドを非静的メソッドに変換するのにコストがかかりすぎるかどうかを調べるために検索を行う場合があります。多くの場合、呼び出しの数が表示され、「わかりました...このメソッドは変更せず、代わりに、必要なことを実行する新しいメソッドを作成する」と言います。
その結果、次のいずれかになります。
それらの両方が悪いです。
したがって、私のアドバイスは、コードベースが200K LOCを超える場合、静的でなければならないメソッドは静的メソッドでなければならないということです。
非静的から静的へのリファクタリングは比較的簡単です(キーワードを追加するだけ)。そのため、後で静的にすることができるようにしたい場合(インスタンス外の機能が必要な場合)、静的にすることができます。ただし、逆リファクタリング、つまり静的になる可能性のあるインスタンスメソッドに変換する方法は、はるかにコストがかかります。
大きなコードベースの場合、エラーはアイデアの純粋さよりも、拡張の容易さの方が優れています。
したがって、大きなプロジェクトでは、必要な場合を除いて、物事を静的にしないでください。小さなプロジェクトの場合は、好きなことをしてください。
私はそれをそのクラスのpublic staticメンバーにするつもりはありません。その理由は、それをpublic staticにすることはクラスのタイプについて何かを言っているからです:「このタイプはこの動作を行う方法を知っている」だけでなく、「この動作を実行するのはこのタイプの責任です」。そして、オッズは、より大きなタイプと実際の関係がなくなった動作です。
だからといって、それをまったく静的にしないわけではありません。これを自問してみてください:新しい方法は論理的に別の場所に属すことができますか?それに対して「はい」と答えることができる場合は、おそらくそれを静的にしたい(そしてそれも移動したい)でしょう。それが真実ではない場合でも、静的にすることができます。マークしないでくださいpublic
。
便宜上、少なくともマークを付けることができますinternal
。これにより、通常、より適切なタイプに簡単にアクセスできない場合にメソッドを移動する必要がなくなりますが、クラスのユーザーへのパブリックインターフェイスの一部として表示されないように、必要な場所にアクセスできます。 。
必ずしも。
パブリックメソッドを静的から非静的に移動することは重大な変更であり、すべての呼び出し元またはコンシューマーを変更する必要があります。メソッドがインスタンスメソッドのように見えても、インスタンスメンバーを使用していない場合は、将来を保証する手段としてインスタンスメソッドにすることをお勧めします。
はい、そうです。様々ながあるカップリングのメトリクスメソッド静的を作るなど、他のクラス、メソッド、のように、あなたのクラスは他のものにどのように依存するかという尺度は、あなたがすることができるため、ダウン結合度を維持する方法であることを確認静的メソッドは、任意の参照していませんメンバー。
個人的には、私は無国籍の大ファンです。あなたのメソッドはクラスの状態にアクセスする必要がありますか?答えが「いいえ」の場合(そしておそらく「いいえ」の場合、そうでなければ、それを静的メソッドにすることを考えないでしょう)、そうです。
州へのアクセスがないことは頭痛の種です。他のクラスでは必要のないプライベートメンバーを非表示にするのが良いのと同じように、それを必要としないメンバーから状態を非表示にするのは良い考えです。アクセスの減少は、バグの減少を意味します。また、静的メンバーをスレッドセーフに保つことがはるかに容易になるため、スレッド化が容易になります。ランタイムは静的メソッドのパラメーターとしてこれへの参照を渡す必要がないため、パフォーマンスに関する考慮事項もあります。
もちろん欠点は、以前の静的メソッドが何らかの理由で状態にアクセスする必要がある場合は、状態を変更する必要があることです。これがパブリックAPIの問題になる可能性があることを理解したので、これがパブリッククラスのパブリックメソッドである場合、おそらくこれの影響について少し考える必要があります。それでも、これが実際に問題を引き起こしたという現実の状況に直面したことはありませんが、たぶん私は幸運なだけかもしれません。
ええ、ぜひやってみてください。
静的メソッドは非静的メソッドよりも高速であるため、そうです。可能な場合は静的メソッドでなければならず、非静的のままにする特別な理由はありません。
実際、ここでカプセル化について言及している人はほとんどいないことに驚いています。インスタンスメソッドは、すべてのプライベート(インスタンス)フィールド、プロパティ、メソッドに自動的にアクセスできます。基本クラスから継承されたすべての保護されたものに加えて。
コードを作成するときは、できるだけ公開しないように、また、アクセスが最小限になるようにコードを記述する必要があります。
したがって、そうです。コードを高速にすることは、メソッドを静的にする場合に発生する可能性がありますが、通常は、コードをできるだけバグを発生させないようにすることよりも重要です。これを実現する1つの方法は、コードが「プライベートなもの」にできるだけアクセスできないようにすることです。
OPは明らかにこのシナリオでうまくいかず、新しいバグを作成できないリファクタリングについて話しているので、これは一見関係がないように見えるかもしれませんが、このリファクタリングされたコードは将来維持し、コードをより大きな「攻撃」にする修正が必要ですプライベートインスタンスメンバーにアクセスできる場合の新しいバグに関しては、「表面」を参照してください。したがって、一般に、ここでの結論は、静的にしない理由が他にない限り、「ほとんどの場合、メソッドは静的でなければならない」ということです。そして、これは単に「カプセル化とデータ非表示をより適切に使用し、「より安全な」コードを作成する」ためです...
個人的には静的にするしかありません。この場合、Resharperは警告を発行し、PMには「Resharperからの警告はありません」というルールがあります。
それは場合によって異なりますが、一般的にはこれらのメソッドを静的にしません。コードは常に変化しており、おそらくいつかその関数を仮想化して、サブクラスでオーバーライドしたいと思うでしょう。あるいは、いつかインスタンス変数を参照する必要があるかもしれません。すべての呼び出しサイトを変更する必要がある場合、これらの変更を行うのは難しくなります。
メソッドとクラスについて考える必要があります。
最後の2つが「はい」の場合、メソッド/クラスはおそらく静的でなければなりません。
最も使用される例は、おそらくMath
クラスです。すべての主要なオブジェクト指向言語にはそれがあり、すべてのメソッドは静的です。インスタンスを作成せずに、いつでもどこでもそれらを使用できるようにする必要があるためです。
もう1つの良い例は、Reverse()
C#のメソッドです。
これはArray
クラスの静的メソッドです。配列の順序を逆にします。
コード:
public static void Reverse(Array array)
すべての配列はArrayクラスのインスタンスであるため、何も返されず、配列が逆になります。
新しいメソッドをprivate staticにする限り、それは重大な変更ではありません。実際、FxCopにはこのガイダンスがルールの1つとして含まれており(http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx)、次の情報が含まれています。
メソッドを静的としてマークすると、コンパイラーはこれらのメンバーに非仮想呼び出しサイトを発行します。非仮想呼び出しサイトを発行すると、現在のオブジェクトポインタがnullでないことを保証する各呼び出しの実行時のチェックが防止されます。これにより、パフォーマンスの影響を受けやすいコードで測定可能なパフォーマンスが向上する可能性があります。場合によっては、現在のオブジェクトインスタンスへのアクセスの失敗は、正確性の問題を表します。
そうは言っても、David Keanの最初のコメントは、懸念をより簡潔に要約したもので、これは実際にはパフォーマンスの向上よりも正しいことのほうが重要だと述べています。
このルールはパフォーマンスの問題として分類されますが、メソッドを静的にすることによるパフォーマンスの向上は約1%にすぎません。むしろ、他のインスタンスメンバーを使用できなかったことにより、メンバーに不完全またはバグがあることを示す可能性のある、より正確な問題です。メソッドを静的(Visual BasicではShared)とマークすると、インスタンスの状態に触れないという意図が明確になります。
なんらかの理由で非静的にされている本質的に静的なメソッドは単に煩わしいものです。ウィットするには:
銀行に電話して残高を要求します。
彼らは私の口座番号を尋ねます。
けっこうだ。インスタンスメソッド。
私は私の銀行に電話して、彼らの郵送先住所を尋ねます。
彼らは私の口座番号を尋ねます。
WTF?失敗-静的メソッドである必要があります。
私はそれを純粋な関数の機能的な観点から一般的に見ています。インスタンスメソッドである必要がありますか?そうでない場合は、ユーザーに変数を渡させて、現在のインスタンスの状態を変更しないことでメリットが得られる可能性があります。(まあ、あなたはまだ状態を壊すことができますが、ポイントは意図的にそうしないことです。)私は一般にインスタンスメソッドをパブリックメンバーとして設計し、プライベートメンバーを静的にするために最善を尽くします。必要に応じて(後で他のクラスに簡単に抽出できます。
これらの場合、私はメソッドをstaticまたはutilsライブラリに移動する傾向があるため、「オブジェクト」の概念と「クラス」の概念を混同しないでください。