関数型言語(Lispなど)では、パターンマッチングを使用して、リスト内の特定の要素に何が起こるかを判断します。C#に相当するのは、要素の型をチェックし、それに基づいて操作を実行するif ... elseifステートメントのチェーンです。言うまでもなく、機能的なパターンマッチングは、実行時の型チェックよりも効率的です。
ポリモーフィズムの使用は、パターンマッチングにより近いものになります。つまり、リストのオブジェクトを特定のインターフェイスと一致させ、各インターフェイスに対してそのインターフェイスで関数を呼び出します。別の代替方法は、特定のオブジェクトタイプをパラメーターとして受け取るオーバーロードメソッドのシリーズを提供することです。Objectをパラメーターとしてとるデフォルトのメソッド。
public class ListVisitor
{
public void DoSomething(IEnumerable<dynamic> list)
{
foreach(dynamic obj in list)
{
DoSomething(obj);
}
}
public void DoSomething(SomeClass obj)
{
//do something with SomeClass
}
public void DoSomething(AnotherClass obj)
{
//do something with AnotherClass
}
public void DoSomething(Object obj)
{
//do something with everything els
}
}
このアプローチは、Lispパターンマッチングの近似を提供します。ビジターパターン(ここで実装されているように、異種リストの使用法の良い例です)。別の例は、優先キューに特定のメッセージのリスナーがあり、責任チェーンを使用してメッセージをディスパッチする場合です。ディスパッチャーはメッセージを渡し、メッセージに一致する最初のハンドラーがそれを処理します。
その反対は、メッセージに登録するすべての人に通知することです(たとえば、MVVMパターンでViewModelの疎結合に一般的に使用されるEvent Aggregatorパターンなど)。私は次の構成を使用します
IDictionary<Type, List<Object>>
辞書に追加する唯一の方法は関数です
Register<T>(Action<T> handler)
(そして、オブジェクトは実際に渡されたハンドラへのWeakReferenceです)。そのため、ここでは、コンパイル時にList <Object>を使用する必要があります。これは、閉じた型が何であるかがわからないためです。ただし、実行時には、辞書のキーであるTypeを強制できます。呼び出すイベントを発生させたいとき
Send<T>(T message)
そして再びリストを解決します。とにかくキャストする必要があるため、List <dynamic>を使用する利点はありません。このように、両方のアプローチにはメリットがあります。メソッドのオーバーロードを使用してオブジェクトを動的にディスパッチする場合、ダイナミックがその方法です。関係なくキャストすることを強制される場合は、Objectを使用することもできます。