なぜ彼らがプライベートなのかを尋ねる代わりに、質問をこれに言い換えましょう:
- 部分的なメソッドがプライベートでない場合はどうなりますか?
この簡単な例を考えてみましょう。
public partial class Calculator
{
public int Divide(int dividend, int divisor)
{
try
{
return dividend / divisor;
}
catch (DivideByZeroException ex)
{
HandleException(ex);
return 0;
}
}
partial void HandleException(ArithmeticException ex);
}
なぜこれを抽象的な方法ではなく部分的な方法にするのかという質問は今のところ無視しましょう(私はそれに戻ります)。HandleException
重要なのは、メソッドが実装されているかどうかに関係なく、これがコンパイルされ、正しく機能することです。誰もそれを実装していない場合、これは例外を食べて0を返します。
次に、ルールを変更して、部分的なメソッドを保護できるとしましょう。
public partial class Calculator
{
// Snip other methods
// Invalid code
partial protected virtual void HandleException(ArithmeticException ex);
}
public class LoggingCalculator : Calculator
{
protected override virtual void HandleException(ArithmeticException ex)
{
LogException(ex);
base.HandleException(ex);
}
private void LogException(ArithmeticException ex) { ... }
}
ここで少し問題があります。HandleException
まだオーバーライドするメソッドがないことを除いて、メソッドを「オーバーライド」しました。そして、私はそのメソッドが文字通り存在しないことを意味します、それはまったくコンパイルされていません。
Calculator
私たちの基地が呼び出すものはどういう意味HandleException
ですか?派生(オーバーライド)メソッドを呼び出す必要がありますか?もしそうなら、コンパイラは基本HandleException
メソッドに対してどのコードを出力しますか?それを抽象的なメソッドに変えるべきですか?空のメソッド?そして、派生メソッドが呼び出すとどうなりますbase.HandleException
か?これは何もしないはずですか?MethodNotFoundException
?_ ここで驚き最小の原則に従うのは本当に難しいです。あなたがするほとんどすべては驚くべきことになるでしょう。
HandleException
または、基本メソッドが実装されていないため、が呼び出されても何も起こらないはずです。ただし、これはあまり直感的ではないようです。私たちの派生クラスはこのメソッドを実行して実装し、基本クラスは私たちが知らないうちにその下からラグを引き出しました。貧しい開発者が髪の毛を抜いて、オーバーライドされたメソッドが実行されない理由を理解できないことは容易に想像できます。
または、このコードはまったくコンパイルされないか、警告が表示されるはずです。しかし、これには独自の問題がいくつかあります。最も重要なことは、部分的なメソッドによって提供されるコントラクトを破ることです。つまり、部分的なメソッドの実装を怠ると、コンパイラーエラーが発生することはありません。基本クラスがうまく機能しているのに、誰かがアプリケーションのまったく異なる部分に完全に有効な派生クラスを実装したために、突然アプリが壊れてしまいます。
また、基本クラスと派生クラスが異なるアセンブリにある可能性についても話し始めていません。「パブリック」部分メソッドを含む基本クラスでアセンブリを参照し、それを別のアセンブリの派生クラスでオーバーライドしようとするとどうなりますか?基本メソッドはありますか、ありませんか?元々、メソッドが実装されていて、それに対して一連のコードを記述したが、誰かが実装を削除することにした場合はどうなりますか?コンパイラーに関する限り、そのメソッドはそもそも存在しなかったため、コンパイラーには、参照クラスからの部分的なメソッド呼び出しをスタブ化する方法がありません。。そこにはありません。コンパイルされたアセンブリのILにはもうありません。だから今、悪影響がないと思われる部分的なメソッドの実装を削除するだけで、依存するコードの束全体が壊れてしまいました。
今、一部の人々は、「だから、私はこの違法なことを部分的な方法でやろうとはしないことを知っている」と言っているかもしれません。理解しなければならないのは、部分メソッド(部分クラスによく似ています)は、主にコード生成のタスクを単純化することを目的としているということです。自分で部分的なメソッドを書きたいと思うことはほとんどありません。一方、マシンで生成されたコードでは、コードの利用者がさまざまな場所にコードを「注入」したいと思う可能性が実際に高く、部分的なメソッドはこれを行うためのクリーンな方法を提供します。
そしてそこに問題があります。部分的なメソッドが原因でコンパイル時エラーが発生する可能性がある場合は、コードジェネレーターがコンパイルされないコードを生成する状況が発生します。これは非常に悪い状況です。お気に入りのデザイナーツール(Linq to SQL、WinformsまたはASP.NETデザイナーなど)が突然コンパイルに失敗するコードの作成を開始した場合の対処方法を考えてみてください。他のプログラマーが、これまでに見たことのない他のクラスを作成したため、部分メソッドに少し親密になりすぎたのでしょうか。
結局のところ、それは実際にははるかに単純な質問に要約されます。パブリック/保護された部分メソッドは、抽象メソッドではまだ達成できないものを追加しますか?パーシャルの背後にある考え方は、それらを具象クラスに置くことができ、それでもコンパイルできるということです。むしろ、それらはコンパイルされませんが、エラーも生成せず、完全に無視されます。しかし、それらが公に呼び出されることを期待する場合、それらはもはや実際には「オプション」ではなく、派生クラスでオーバーライドされることを期待する場合は、抽象的または仮想的で空にすることもできます。コンパイラと貧弱な野郎がすべてを理解しようとしていることを混乱させる以外に、パブリックまたは保護された部分メソッドの使用は実際にはありません。
したがって、チームは、そのPandoraのボックスを開く代わりに、それを忘れると言いました。パブリック/保護された部分メソッドは、とにかくあまり使用されないので、プライベートにするだけです。そうすれば、すべてを安全で正気に保つことができます。そしてそうです。部分的なメソッドが非公開である限り、それらは理解しやすく、心配がありません。そのままにしておきましょう!