はかせのラボ

私の頭の中を書いていく雑記ブログです

C# ブログリハビリがてらC#で作れるプロパティについて雑多に書いてみる

あいさつ

かな~~~~りお久しぶりです。hakaseです。

以前更新したのはえーっと、
f:id:hakase0274:20200922010152p:plain
5/31ですか。
今はもう9月中旬が終わりそうなあたりなので、
約4ヶ月ほど更新が止まってしまっていたわけですか。

誠に申し訳ございませんorz
(というか最後の更新もなんか謝ってますね)

全力言い訳タイム

言い訳させてもらうと新社会人になって物理的に死んでたんですよ。
特にコロナの影響で最初の2,3ヶ月自宅待機命令が出て、研修が遅れに遅れ、
その遅れを取り返すごとく詰まりに詰まった日々を過ごしておりました。

じゃあこの記事書いてるってことはその日々が終わったのかと言われると、
そうでもなく久しぶりにブログ書きたいなぁと思ったから書いております。

というか社会人やりながら趣味活動するのってかなり無理ゲーじゃないです?
1日の約3分の1が仕事でむしられるわけですよ?

しかも残りの3分の2はそのまままるっと使えるわけじゃなくて、
睡眠時間やら家事の時間やらのアクションで細々と時間を
むしられて結局1日数分しか空き時間がないなんていう事態が
ザラで起きるんですけど?

私は幸いなことに好きなことを仕事にできたので、
病んだりは今のところしてませんが、
これが好きでもなんでもないことが仕事になっていたらと考えると、
とてもじゃないけど無理です。はい。

ただアクセスログを見る限り全く更新されていないのにもかかわらず、
100~200PV/日のアクセスがあったようで、いやぁありがたいですね。
これからも当ブログをよろしくお願いいたします。

C#のプロパティについて

たまにQiitaとかのサンプルで見るこんなやつです。

// 定義側
class Sample
{
    private int hoge = 0;
    public int Hoge
    {
        get 
        {
            return hoge;
        }
        set 
        {
            hoge = value;
        }
    }
}

// 使う側
class SampleUse
{
    private Sample sample;
    private void Main()
    {
        sample = new Sample();
        // Hogeのset
        sample.Hoge = 10;
        // Hogeのget
        Console.WriteLine(sample.Hoge); // 10
    }
}

書き方はSampleクラスのHogeという変数を触っているようですが、
実はHogeのget/setをそれぞれしれっと呼び出しているわけですね。

今回の例はあくまでサンプルとして書いてるのであっさりしてますが、
実際はget/setはアクセスレベルをそれぞれ指定できますし、
中身もゴリゴリに実装可能です。

めんどくさければ

// 定義側
class Sample
{
    public int hoge{ get ;set; } = 0;
}

こんな感じで変数宣言の後ろにつけてプロパティ化できます。
アクセスレベルの指定もできるので、

// 定義側
class Sample
{
    public int hoge{ get ; private set; } = 0;
}

外部からは読み取りのみ可能な変数を書くこともできます。
readonlyとかと違うのは該当クラス内ならコンストラクタ外でも編集が可能ってとこですかね。

メリットは何があるの?

ぶっちゃけていいます。
性能的なメリットはありません。

あとでミニコラム的な感じで載せますが、
最終的には該当する関数呼び出しに置き換わるだけなので
素直にgetter/setterを作って操作するのと
パフォーマンス的には大差ありません。

じゃあC#のプロパティ使うと何が嬉しいの?という話ですが、
私は以下の嬉しい点があると思ってます。
・書く量が減る
・変数呼出と同じ書き方で行けるから使う側で意識しなくていい

つまりどういうことかっていうと、
”使う側も作る側も楽になる”
ただただこれに尽きます。

書く量に関してはさっきのサンプルを見てもらえばわかるように、
最短1行でgetter/setterの実装が完了します。
getter/setterを素直にメソッドで作ろうとすると、

class Sample
{
    private int hoge = 0;
    public int GetHoge()
    {
        return Hoge;
    }   
    public void SetHoge(int value)
    {
        Hoge = value;
    }
}

操作対象の変数宣言込みで9行ですね。
つまりプロパティ使うとコード量が9分の1になるわけです。(極論ですが)

使う側が楽ってのもサンプルで載せたように、
あたかも該当クラスの変数を直接触っているような
感じで書けます。

もちろん言語機能なのでアクセスレベル違反の操作を行おうとすれば、
赤エラーがでます。わかりやすいですね。

デメリットってあったりする?

特にないです。
強いて言えばC#に慣れてない人が見ると
はてなマークが少し出るくらいです。

プロパティがどうやって実行されるのか

変数宣言にちょっと追加するだけでgetter/setterが勝手に追加されて、
それが呼び出される謎機能プロパティ。

ここではそれが実際どうやって実装し呼ばれているのか
ILを見て追ってみましょう。
下記画像は最初にあげたサンプルをSharpLabという神サイトにあげて、
IL変換させたやつです。
f:id:hakase0274:20200922020249p:plain

プロパティの実装部分はこの辺です。
f:id:hakase0274:20200922020646p:plain
get_Hogeとset_Hogeという名前のメソッドが作られています。

そしてこれが呼び出し部分です。
f:id:hakase0274:20200922020806p:plain

要はプロパティで書いたものは最終的に
get_+変数名のgetterとset_+変数名のsetterを自動生成して
置き換えているだけってことですね。

ちなみに最終的にそういう名前のメソッドが生まれることは
IDE側で検知できるのでそういう名前のメソッド作ろうとしたら
赤エラー吐かれます。
気になる方は手元のVisualStudio等で試してみてください。

あとがき

今回はかなり久しぶりのブログ更新で、
C#のプロパティについて雑多に書いてみました。
久しぶりに書いたのでかなりつたない部分もあったかと思いますが、
何卒ご容赦ください。
(えっ前もつたなかった?そういうのは言わぬが花ってやつですよ?)

それでは今回はこの辺でノシ