4

同じアセンブリ内の2つのクラス:Class AおよびStatic Class B

のメソッドでClassA、私はでメソッドを呼び出していますが、そのメソッドを呼び出すClassBたびにではなく、1回だけ呼び出されるようにしたいのですが、ClassA現在、グローバルプロパティ-Ran-を設定しています。そのメソッドが以前に実行されたかどうかを確認するために...まあそれは機能しますが、これは最良の設計ではないと感じています。同じことをするより良い方法があるかどうか疑問に思いましたか?

ありがとう。

ClassA.MyMethod(...)
{
....
//.... 
if (ClassB.Ran != 1)
    ClassB.Foo();
....
//...
}
4

5 に答える 5

9

「1回だけ」の制限がどの程度厳密に解釈されるかに注意する必要があります。静的メソッドは通常、スレッドセーフであると見なされます。レーシングスレッドの場合でも、メソッドが1回だけ実行されるようにしたい場合は、同期メカニズムを使用する必要があります。最も簡単な例は次のlockとおりです。

private static bool isRun = false;
private static readonly object syncLock = new object();

public void MyMethod()
{
    lock (syncLock)
    {
        if (!isRun)
        {
            Foo();            
            isRun = true;
        }
    }
}
于 2012-05-03T18:46:11.220 に答える
8

私は通常これを行いますLazy<T>

検討:

public static class Test // this is your ClassB
{
    private static Lazy<string> m_Property = new Lazy<string>( ()=>
    {
        Console.WriteLine("Lazy invoked"); 
        return "hi";
    },true);
    public static string Property
    {
        get
        {
            Console.WriteLine("value request");
            return m_Property.Value;
        }
    }
}

//....consuming code, this is in your ClassA somewhere

var test1 = Test.Property; // first call, lazy is invoked
var test2 = Test.Property; // cached value is used, delgate not invoked
var test3 = Test.Property; // cached value is used, delgate not invoked
var test4 = Test.Property; // cached value is used, delgate not invoked
var test5 = Test.Property; // cached value is used, delgate not invoked

これは出力です:

value request
Lazy invoked
value request
value request
value request
value request
于 2012-05-03T18:42:33.280 に答える
5

クラスでプライベート静的フィールドを使用して、メソッドが最初に呼び出されたときに結果が設定され、再度実行されないようにすることができます。

class B
{
  private static bool fooRun = false;

  public static void Foo()
  {
    if (fooRun) { return; }
    ...
    fooRun = true;
  }
}
于 2012-05-03T18:41:00.320 に答える
1

実行するかどうかに関係なく、コンストラクターに bool を渡すだけですか? 何かのようなもの:

ClassA(bool runA)
{
    if (runA) 
    {
        ClassB.Foo();
    }
}
于 2012-05-03T18:38:07.450 に答える
1

これ以上詳細がないと、なんとも言えませんが、クラス B のこのメソッドには、ある種の初期化ロジックが含まれているようです。クラス B が初めて参照されたときにのみ発生する必要がある場合は、クラス B の静的コンストラクターに配置できます。クラス A が参照されたときにのみクラス B のメソッドを実行する必要がある場合は、クラスAの静的コンストラクターから呼び出されます。クラスAのメソッドが呼び出されるまで呼び出すことができず、どこからでも一度だけ呼び出す必要がある場合は、クラスBのプライベート静的変数を内部からチェックする必要がありますメソッドを呼び出し、既に呼び出されている場合はすぐに戻ります。それ以外の場合は、最後の手段として、クラス A にプライベートな静的変数を設定する方が、グローバル変数よりも望ましいと言えます。

ただし、これらすべてのケースで、グローバルな状態を作成していると言えます。これは、ほとんどの場合、設計が不十分であることを示しています。私の謙虚な意見では、この種の問題は、「依存性注入」の必要性を叫んでいるだけです。

于 2012-05-03T18:55:45.030 に答える