2

与えられた:

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 行だけ使用できる一般的な実装に置き換えたいと考えています。この一般的なメソッド/クラスを実装する簡単な方法はわかりませんが、私の本能はそれが可能であるべきだと教えてくれます。

どんな助けでも大歓迎です。

4

6 に答える 6

16

メソッドをインターフェース内に配置し、ポリモーフィズムにどのメソッドを呼び出すかを決定させます

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.メソッドに触れる必要はありません。

于 2008-10-06T04:02:06.903 に答える
5

欲しいのは二重発送、特にビジターパターン

于 2008-10-06T06:57:27.047 に答える
1
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 });
    }
}
于 2008-10-06T22:11:33.117 に答える
1

これはちょっと醜いですが、仕事を成し遂げます:

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);
}

とはいえ、こんな風にはしないと思います。それは実際にそれを見るのが痛いです。こちらも無理やり見てしまい申し訳ありませんでした。

于 2008-10-06T05:26:33.300 に答える
0

C# では便利な形式では存在しません - F# のパターン マッチングに基づくアイデアについては、こちらを参照してください。実行時にオーバーロードを選択するためにリフレクションを使用していくつかのことを行うことができますが、それは非常に遅くなり、両方のオーバーロードを満たすものがあると深刻な問題が発生します。戻り値がある場合は、条件演算子を使用できます。

return (I is B) ? Method((B)I) : ((I is C) ? Method((C)I) : 0);

繰り返しますが、きれいではありません。

于 2008-10-06T04:01:20.243 に答える
0

簡単。Visual Basic では、CallByName を使用して常にこれを行っています。

Sub MethodBase(value as Object)
    CallByName(Me, "RealMethod", CallType.Method, value)

これにより、実行時の値の型に最も近い RealMethod のオーバーロードが呼び出されます。

Microsoft.VisualBasic.Interaction をインポートするか、リフレクションを使用して独自のバージョンを作成することで、C# から CallByName を使用できると確信しています。

于 2008-10-06T05:28:41.860 に答える