13

注: 私は C#、Java、および C++ に最も興味がありますが、これはよりアカデミックな質問であるため、どの言語でも行うことができます。

この問題は、指定された言語の適切なメソッドを使用して ( freeDispose、またはインスタンスへのすべての参照を削除することによって)、外部から解決できることを知っています。

私の考えは、インスタンスを作成し、コンストラクターでプライベートタイマーを開始することです。タイマーが終了すると、インスタンス メソッドが呼び出され、変数が破棄されます。

C# では、実装Dispose時に自分自身を呼び出すことができるはずIDisposableですが、これはインスタンスを破壊しません。

C++ では を呼び出すことができますがdestructor、それはメモリ リークにつながります。さらに、これは本当に悪い習慣です。

Javaでは手がかりがありません。フィールドであるため、割り当てることthisはできません。final

たとえば、自己を破壊する方法はありますか?

4

8 に答える 8

10

あなたの質問は非常に興味深いものです.C#でそうする他の方法は知りませんが、インスタンスの内側から強制的に外側から破壊する方法はありません. それで、これが可能かどうかを確認するために私が思いついたものです。Fooタイマーの特定の間隔が経過したときに発生するイベントを持つクラスを作成できます。イベント内でそのイベント ( Bar) に登録されているクラスは、イベントを登録解除し、インスタンスの参照を に設定しますnull。これは私がそれを行う方法であり、テストされ、機能します。

public class Foo
{
    public delegate void SelfDestroyer(object sender, EventArgs ea);

    public event SelfDestroyer DestroyMe;

    Timer t;

    public Foo()
    {
        t = new Timer();
        t.Interval = 2000;
        t.Tick += t_Tick;
        t.Start();
    }

    void t_Tick(object sender, EventArgs e)
    {
        OnDestroyMe();
    }

    public void OnDestroyMe()
    {
        SelfDestroyer temp = DestroyMe;
        if (temp != null)
        {
            temp(this, new EventArgs());
        }
    }
}

public class Bar
{
    Foo foo;
    public Bar()
    {
        foo = new Foo();
        foo.DestroyMe += foo_DestroyMe;
    }

    void foo_DestroyMe(object sender, EventArgs ea)
    {
        foo.DestroyMe -= foo_DestroyMe;
        foo = null;
    }
}

これをテストするには、次のようにフォーム内でボタンのクリックを設定し、デバッガーで確認します。

Bar bar = null;
private void button2_Click(object sender, EventArgs e)
{
       if(bar==null)
             bar = new Bar();
}

そのため、次にボタンをクリックすると、Barインスタンスがまだ存在していることがわかりますが、そのインスタンスはのコンストラクターFoo内で作成されていますが、その中のインスタンスは nullです。Bar

于 2013-07-05T10:54:34.273 に答える
3

C++: オブジェクトが動的に割り当てられた場合、そのオブジェクトの this ポインターをそれ自体の関数で削除することができます。

于 2013-07-05T10:43:22.990 に答える
2

いいえ、 でやろうとしていることを達成する方法はありませんC#

例を考えると:

public class Kamikadze {

     ......             
     private void TimerTick(..) 
     {
        ....
        if(itsTime) {
            DestroyMe();
        }
     }

     .....
}


var kamikadze = new Kamikadze ();

しばらくすると、内部データを消去DestroyMe()する が呼び出されます。

ただし、参照kamikadze(必要に応じてポインター) は引き続き有効であり、そのメモリの場所を指しているため、GC何も実行せず、収集せず、インスタンスはKamikadzeメモリに残ります。

于 2013-07-05T10:30:52.850 に答える
0

C++ では、自殺するインスタンスは、Finite State Machine パターンの不可欠な部分です。

//Context class contains a pointer to a State object.

void BattleshipGame::SetGameState(IState* state) {
    game_state = state;
}

void BattleshipGame::Loss() {
    game_state->Loss(this);
}

void BattleshipGame::Idle() {
    game_state->Idle(this);
}

void BattleshipGame::FlyBy() {
    game_state->FlyBy(this);
}

void BattleshipGame::Attack() {
    game_state->Attack(this);
}

void BattleshipGame::Win() {
    game_state->Win(this);
}

void BattleshipGame::Load() {
    game_state->Loading(this);
}

//State base class contains methods for switching to every state.
class IState {
public:
    virtual void Loading(BattleshipGame* context);
    virtual void Idle(BattleshipGame* context);
    virtual void FlyBy(BattleshipGame* context);
    virtual void Attack(BattleshipGame* context);
    virtual void Win(BattleshipGame* context);
    virtual void Loss(BattleshipGame* context);
protected:
private:

};

//Implementations in the State base class are defined, but empty.

//Derived States only call what they need:

void StateIdle::Loss(BattleshipGame* context) {
    //context->SetGameState(new StateLoss());
    context->SetGameState(new StateLoss(context));
    delete this;
}

void StateIdle::Idle(BattleshipGame* context) {
    context->SetGameState(new StateIdle());
    delete this;
}

void StateIdle::FlyBy(BattleshipGame* context) {
    context->SetGameState(new StateFlyBy());
    delete this;
}

void StateIdle::Win(BattleshipGame* context) {
    context->SetGameState(new StateWin());
    delete this;
}

//Similar design for all other states...
于 2013-07-05T12:00:18.953 に答える