2

クラスのクライアントがオーバーライドできるようにしたいいくつかの機能を持つ C# クラスがあります。具体的には、次のことを希望します。

  1. クライアントが何もしない場合、デフォルトの動作が得られます
  2. クライアントは動作をオーバーライドして、デフォルトの動作が呼び出されないようにすることができます。
  3. クライアントは動作をオーバーライドして、デフォルトの動作を pre/post/middle 操作として呼び出すことができます。

私の現在の考えは次のとおりです。

  1. クライアントが動作をオーバーライドしたい場合にサブスクライブするイベントを公開します。
  2. デフォルトの動作 (イベントのシグネチャと一致する) でメソッドを公開します。 void DefaultBehavior()
  3. イベントを起動しようとするたびに、デリゲートが null の場合は、デフォルトの動作メソッドを呼び出します。それ以外の場合は、イベントのデリゲートを呼び出します。

    if (eventDelegate == null)
        DefaultBehavior();
    else
        eventDelegate();
    

クライアントが動作をオーバーライドする場合、必要に応じて DefaultBehavior メソッドを呼び出して、目的の動作を取得できます。

このアプローチは、クライアントの観点から十分に直感的だと思いますか? または、より良い代替案を提案できますか?

4

4 に答える 4

8

クライアントに何らかの動作をオーバーライドさせたい場合は、仮想関数を作成して、クライアントに実際に実行させてみoverrideませんか?

これは、これを達成するための簡単な方法です。車輪を再発明する必要はありません。

于 2012-06-14T21:56:39.833 に答える
2

私があなたの質問を理解していれば、clientこのようにする必要があると仮定して、クラスを呼び出し、クラスをオーバーライドしないコードを意味します(そのようにすることができれば@zmbqの回答に同意します):

メソッドに 2 つのオーバーロードを持たせることができます。1 つはパラメーターなしで、もう 1 つはActionオブジェクトを受け取ります。

public void methodName()
public void methodName(Action delegate)

次に、本体でmethodName()defaultAction を使用して他のメソッドを呼び出します

public void methodName()
{
  methodName(DefaultBehavior);
}

最後に、2 番目のメソッドでは、パラメーターとして渡されたデリゲートを呼び出すだけで、それがデフォルトかどうかを気にする必要はありません。

public void methodName(Action delegate)
{
 delegate();
}

クラスのクライアントは、この 2 つのオーバーロードを見て、デフォルトを使用するかカスタム動作を与えるかを決定します

編集: わかりました、最後の試み:)、あなたの最後のコメントによると、インスタンスフィールドを持つことはうまくいきます

private Action behaviorDelegate = DefaultBehavior;

クラスのどこでも別の動作に割り当てることができます。デフォルトであるかどうかにかかわらず、動作は常に変数になるためbehaviorDelegate、ステートメントは必要ありません。それは大きな変化ではありませんが、私にはきれいに見えます。ifdelegate

于 2012-06-14T22:00:56.060 に答える
1

あなたは(おそらく?)イベントなしでそれを行うこともできます:

宣言:

public class DemoClass
{
    public delegate string MyDelegate(string testValue);

    public static MyDelegate DefaultBehavior
    {
        get
        {
            return testValue => 
              { 
                 return String.Concat(testValue, 
                                      ", now with 99% more exclamation points!!!!!!!!"); 
              };
        }
    }

    public MyDelegate ModifyString = testValue => 
        { 
           return DemoClass.DefaultBehavior(testValue); 
        };
}

使用する:

// first, default:
DemoClass demoObject = new DemoClass();
Console.WriteLine(demoObject.ModifyString("My test string")); 

// now, pure "override":
demoObject.ModifyString = testVal => 
        { return String.Concat(testVal, ", this time with question marks????"); 
        };
Console.WriteLine(demoObject.ModifyString("Second test string"));

// finally, define a delegate that overrides and calls default:
DemoClass.MyDelegate combined = testVal => 
        { return String.Concat(DemoClass.DefaultBehavior(testVal), 
                               ", now we're really tricky"); 
        };
demoObject.ModifyString = combined;
Console.WriteLine(demoObject.ModifyString("Third test string"));

出力:

私のテスト文字列は、感嘆符が 99% 増えました!!!!!!!!
2 番目のテスト文字列。今回は疑問符が付きます????
3 番目のテスト文字列、感嘆符が 99% 増えました!!!!!!!!、これで本当にトリッキーになりました
于 2012-07-16T19:48:03.730 に答える
0

仮想メソッドを使用するだけです:

public class BaseClass {
   public virtual void Something() {
      Console.WriteLine("base functionality");
   }
}

public class Sub1 : BaseClass {
   public override void Something() {
       // do whatever you want here
       base.Something();  // don't call it at all if you like
       // do whatever you want here
   }
}
于 2012-06-14T22:12:18.977 に答える