質問
指定:
interface I
{
}
class B: I
{
}
class C: I
{
}
class A
{
public void Method(B arg)
{
}
public void Method(C arg)
{
}
public void Method(I arg)
{
// THIS is the method I want to simplify.
if (I is B)
{
this.Method(arg as B);
}
else if (I is C)
{
this.Method(arg as C);
}
}
}
この種の相互作用を設計するより良い方法があることは知っていますが、 これを説明するには時間がかかりすぎる詳細は不可能です。 このパターンは何回も複製されるので、 1行だけで使用できる一般的な実装の条件付きロジック。 この一般的なメソッド/クラスを実装する簡単な方法はわかりませんが、私の直感はそれが可能であるべきだと言っています。
ご協力いただければ幸いです。
他のヒント
インターフェイス内にメソッドを配置し、ポリモーフィズムにどのメソッドを呼び出すかを決定させます
interface I
{
void Method();
}
class B : I
{
public void Method() { /* previously A.Method(B) */}
}
class C : I
{
public void Method() { /* previously A.Method(C) */ }
}
class A
{
public void Method(I obj)
{
obj.Method();
}
}
新しいクラスを追加する必要があるときは、I.Methodを実装するだけです。 A.Methodに触れる必要はありません。
これはちょっとugいですが、仕事は完了です:
public void Method(B arg)
{
if (arg == null) return;
...
}
public void Method(C arg)
{
if (arg == null) return;
...
}
public void Method(I arg)
{
this.Method(arg as B);
this.Method(arg as C);
}
しかし、私はこのようにするつもりはありません。実際にそれを見ると痛いです。申し訳ありませんが、皆さんにもこれを見てもらいました。
interface I
{
}
class B : I
{
}
class C : I
{
}
class A
{
public void Method(B arg)
{
Console.WriteLine("I'm in B");
}
public void Method(C arg)
{
Console.WriteLine("I'm in C");
}
public void Method(I arg)
{
Type type = arg.GetType();
MethodInfo method = typeof(A).GetMethod("Method", new Type[] { type });
method.Invoke(this, new I[] { arg });
}
}
C#を使用した便利な形式では存在しません-アイデアについては、こちらをご覧ください F#のパターンマッチングに基づいて、希望どおりに動作します。実行時にオーバーロードを選択するためにリフレクションを使用していくつかのことを行うことができますが、それは非常に遅くなり、両方のオーバーロードを満足させるものがあると深刻な問題が発生します。戻り値がある場合は、条件演算子を使用できます;
return (I is B) ? Method((B)I) : ((I is C) ? Method((C)I) : 0);
また-可愛くない。
簡単。 Visual Basicでは、CallByNameを使用して常にこれを行います。
Sub MethodBase(value as Object)
CallByName(Me, "RealMethod", CallType.Method, value)
これは、値のランタイムタイプに最も近いRealMethodのオーバーロードを呼び出します。
Microsoft.VisualBasic.Interactionをインポートするか、リフレクションを使用して独自のバージョンを作成することにより、C#からCallByNameを使用できると確信しています。