0

私がゲームを作っていて、基本Buffクラスを持っているとしましょう。クラスのイベントThornsBuffをサブスクライブするという名前のサブクラスもあるかもしれません。PlayerDamaged

にはのPlayerリストがありBuff、そのうちの1つはThornsBuffです。例えば:

テストクラス

Player player = new Player();
player.ActiveBuffs.Add(new ThornsBuff(player));

ThornsBuffクラス

public ThornsBuff(Player player)
{
    player.DamageTaken += player_DamageTaken;
}

private void player_DamageTaken(MessagePlayerDamaged m)
{
    m.Assailant.Stats.Health -= (int)(m.DamageAmount * .25);
}

これはすべて例を説明するためのものです。リストからバフを削除した場合、イベントは切り離されません。プレイヤーがバフを持っていなくても、イベントは彼が持っているかのように実行されます。

これで、イベントの登録を解除するメソッドを作成できましたが、リストからを削除するだけでなくDispel、開発者が呼び出す必要があります。彼らが忘れたり、カップリングを増やしたりした場合はどうなりますか?DispelBuff

Buff私が理解していないのは、がリストから削除されたときにイベントが自動的に切り離されない理由です。Buffリストに存在するのは1つだけで、それが1つの参照です。それが削除された後、イベントは切り離されるべきではありませんか?

デタッチコードをのファイナライザーに追加しようとしましたが、Buffそれでも修正されませんでした。参照が0になった後でも、イベントは引き続き実行されます。ガベージコレクターがまだ実行されていなかったためだと思いますか?オブジェクトに参照がない場合にすべてのイベントが登録されないように、自動かつ瞬時に作成する方法はありますか?

ありがとう。

4

2 に答える 2

1

イベント(player_DamageTaken)は、バフがActiveBuffsリストにあるかどうかに関係なく、引き続き呼び出されます。これは、DamageTaken + = player_DamageTakenを実行すると、player.DamageTakenからThornsBuffのインスタンスとそのplayer_DamageTakenメソッドへの参照が作成されるためです。(それ以外の場合、ランタイムは、player_DamageTakenを呼び出すThornsBuffのインスタンスをどのように知るのでしょうか?)

その参照は、player.DamageTaken- = player_DamageTakenを呼び出すまで存在し続けます。バフをActiveBuffsに追加するという事実は、バフへの別の参照を追加するだけであり、技術的には必要ありません(ただし、参照されていないイベントハンドラーがぶら下がっているのは好きではないので、私の意見では良い形式です)。

開発者に追加のDispelまたはDisposeメソッドを呼び出させずに、イベントハンドラーを削除する方法を疑問に思っているかもしれません。そのために、いくつかの提案があります。

  1. player_DamageTakenの先頭で、player.ActiveBuffs.Contains(this)かどうかを確認し、そうでない場合は、player.DamageTaken-=player_DamageTakenを呼び出して戻ります。これの欠点は、バフがダメージを受けるたびにバフのリスト全体を検索することです。

  2. ActiveBuffsをObservableCollection(または同様のもの)にして、バフがリストから削除されたときにリッスンできるようにします。その場合、buff.Dispelを自動的に呼び出すことができるため、開発者はそれを呼び出すことを覚えておく必要がありません。

于 2012-11-18T04:47:30.513 に答える
0

私が理解していないのは、バフがリストから削除されたときにイベントが自動的に切り離されない理由です。

バフをリストに添付することは、イベントを添付するものではなかったからです。コンストラクターでイベントをアタッチしたため、イベントがアタッチされました。プレーヤークラスインスタンスには、DamangeTakeイベントでそのバフへの参照も含まれるようになったため、バフリストから削除しても、オブジェクトをガベージコレクションするのに十分ではありません...したがって、バフは存続します。

なぜここでイベントを使用するのか不思議に思います。リスト内の各バフを繰り返し、インターフェースの一部として定義されたメソッドを実行し、引数または戻り値としてダメージを与えるコードをプレーヤーに含めるだけではどうでしょうか。それはあなたが探していることをもっとするでしょう。

または、現在バフを削除している場所では、イベントの登録を解除するためのコードも必要になります。

于 2012-11-18T04:57:35.150 に答える