私は興味深い問題を抱えていますが、私は静かに解決策を見つけているようには見えません。
私は防御的なプログラマーになる傾向があるので、問題が発生してから対処するのではなく、問題が発生しないようにするコードを書くようにしています。そのために、私は次のような状況にあります。次のコードを使用します。
public class Base {}
public Interface IBase {}
public class Derived : Base, IBase {}
public class Derived2 : Base, IBase {}
...
public class DerivedN : Base, IBase {}
public class X : Base {}
public class Y : IBase {}
Base から派生し、IBase を実装するオブジェクトのリストをコレクションに渡す必要があり、両方を持つオブジェクトのみがリストに追加されるようにする必要があります。さらに、両方を持つ任意の数のクラスが存在する可能性があるため、派生クラスを制約として使用することはできません。
Base 型のリストを作成すると、Y オブジェクトを追加できます。IBase 型にすると、X 型のオブジェクトを追加できます (どちらも許可されません)。
もちろん、両方の型を持ち、両方の制約を持つ独自のジェネリック コレクション クラスを作成することもできます。しかし、考えられるすべてのコレクション型に対してこれを行う必要はありません。また、すべての機能を複製するには多大な労力が必要です (メソッド呼び出しを含まれているクラスに転送するだけでも)。
また、Base と IBase の両方から派生する BaseWithIBase クラスを作成し、それをコレクション タイプとして使用することもできますが、必要がなければ別の抽象化を強制したくありません。
これを実行時チェックにしたくないので、ツリーをたどって例外をスローすることは受け入れられません。
誰でもこの問題に対するより良いアプローチを提案できますか?
注: Base と IBase は関連がなく、どちらも異なるタイプの基本アイテムであることを指摘するだけです。
編集:
誰もが「そんなことする必要はない」「OOP ではない」と主張したいようです。真実と違うことがあってはならない。この種の質問やコメントを防ぐために、質問から特定のものを削除しようとしていたので、私の実際の状況を含めます。
このコードは、.NET Framework の ServiceProcess.ServiceBase クラスに基づく Windows サービス フレームワークの実装です。この上に独自のフレームワークを追加しています。これは、依存性注入に大きく基づいており、高度にテスト可能であることを目的としています。
コレクションには、ServiceBase と IService の両方から派生したオブジェクトが含まれている必要があります。IService は、コード内およびテスト用に使用される私のフレームワーク拡張機能です。基本的にはこれだけです:
public interface IService
{
void Start();
void Stop();
}
さらに、他にもいくつかのインターフェースがあります。
public interface IRestartableService
{
void Restart();
}
public interface IConfigurableService
{
void Configure();
}
etc.. etc.. サービスは次のようになります。
public class MyService : ServiceBase, IService, IConfigurableService {}
私のコードには IService が必要で、Windows には ServiceBase が必要です。したがって、私は IService を使用し、Windows は ServiceBase を使用するため、両方が必要です。IService のみが必要です。その他のインターフェイスはオプションです。