LoginSignup
3
1

More than 3 years have passed since last update.

C#のプロパティの用法についての思案メモ

Last updated at Posted at 2019-06-08

書き出し

とあるUnityのフレームワークの中で見つけたコードです。

int Counter;

void Update()
{
    if (Counter > 100)
    {
        // カウントが閾値を超えたときの処理
    }
}

なぜCounterに値を代入した際にチェックしないでUpdateで毎フレームチェック1しているのか……謎。
こういうときはプロパティを使ったほうがいいのでは……と思ったのですが、自分もプロパティってあまり使ったことがないなーと思ったので自分が思いつくなりの用法をメモします。
ざっと調べた感じ、プロパティの使い方についての記事は出てきても「どう使うか」を実際に解説した記事は見当たらなかったので。

プロパティとはなんぞや、という方は以下の記事を参照。
プロパティ - C# によるプログラミング入門 | ++C++; // 未確認飛行 C

使い方メモ

リスナの登録管理

private bool _isListening = false;

private bool IsListening
{
    get => _isListening;
    set
    {
        if (_isListening == value)
        {
            return;
        }

        _isListening = value;
        if (_isListening)
        {
            ExampleEvents.ExampleEvent += ExampleEventHandler;
        }
        else
        {
            ExampleEvents.ExampleEvent -= ExampleEventHandler;
        }
    }
}

IsListeningtruefalseを入れるだけでリスナの登録を管理できます。いろんなタイミングでリスナを登録/解除しているとカオスになるので、これを使うとかなり楽になります。探すときもIsListeningを検索するだけでいいし。

ログ出し

public enum BadStatus
{
    None,
    Poison,
    Paralyze,
}

private BadStatus _status = BadStatus.None;

public BadStatus Status
{
    get => _status;
    set
    {
        Debug.Log($"{_status} => {value}");
        _status = value;
    }
}

enumでStateを定義するのはよくあることだと思います。
以下のように変化させると

Status = BadStatus.Poison;
Status = BadStatus.Paralyze;
Status = BadStatus.None;

こんな感じでログが出ます。

ログ
None => Poison
Poison => Paralyze
Paralyze => None

ステート遷移の解析に役立ちます。重要なのはNone => Noneなど、同じステートへの変化でもログを省略しないこと。
うっとうしいですがその方が解析が楽です。

値のバリデート

public readonly int MaxHp = 200;
public int _hp;

public int HP
{
    get => _hp;
    set
    {
        if (value < 0)
        {
            value = 0;
        }
        else if (value > MaxHp)
        {
            value = MaxHp;
        }

        Debug.Log($"{_hp} => {value}");
        _hp = value;
    }
}

ゲームでよくあるHPの管理。
ダメージを受けたり回復されたり。

HP = 100;
HP -= 300;
HP += 10;
HP += 999999999;

どれだけ食らっても一定の範囲内に収まります。

ログ
0 => 100
100 => 0
0 => 10
10 => 200

だんだん状態異常が効かなくなってくるやつ

public int ResistancePoison = 40;
public int _accumulatedPoison = 0;

public int AccumulatedPoison
{
    get => _accumulatedPoison;
    set
    {
        _accumulatedPoison = value;
        if (_accumulatedPoison > ResistancePoison)
        {
            Status = BadStatus.Poison;
            _accumulatedPoison = 0;
            ResistancePoison += 20;
        }
    }
}

毒の蓄積値が閾値以上になると値をリセットして毒状態になり、閾値を大きくします。

AccumulatedPoison += 50;
Debug.Log("Cure!");
Status = BadStatus.None;
AccumulatedPoison += 50;
Debug.Log("again...");
AccumulatedPoison += 50;
ログ
None => Poison
Cure!
Poison => None
again...
None => Poison

感想

めっちゃバグりそう
値のバリデートやログ出し程度に留めておかないと変な穴2にハマって死にそうですね。
あとクラスのメンバ変数をクラスの上に書く基本のスタイルだと、変数の部分にロジックが混ざってめっちゃ読みづらそうです。
最近はIDEがかしこいので変数とメソッドを取り混ぜて書いても3なんとかなりますが、なんとかなるってだけでつらいです。すごくつらい。

なんかいい使い方あるよって方はなんか書いてわたしの蒙を啓いてください。

おしまい。


  1. 処理をUpdateのタイミングで行う必要もない... 

  2. kotlinだとfield知らないとしぬ 

  3. いやいるんですよそんなことする奴……いるんですよ! しかも新しく書いたやつから下に書いてるだけで特に並びに関連性があるわけでもなく…… 

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1