プロパティのなぞその2

        public Vector2 Velocity {
            get { return velocity; }
            private set { Velocity = value; }
        }
        Vector2 velocity;

このように書くとスタックオーバーフローのランタイムエラーが出る。 正解は

        public Vector2 Velocity {
            get { return velocity; }
            private set { velocity = value; }
        }
        Vector2 velocity;

である。 また、これを

       public Vector2 Velocity { get; private set; }

と(C# 3.0ならば)書いてもよさそうだが、 そうすると Velocity.X = 1.0; とか書くとエラーになる。 なので、結局正解は

        public Vector2 Velocity {
            get { return velocity; }
        }
        Vector2 velocity;

と書いた上で velocity.X = 1.0; などと書かなくてはならない。 プロパティってなんかおもしろいな。 ていうか便利なのかどうかわからん状況もあるようだ。

        private Tile LoadGemTile(int x, int y, GemType type)
        {
            Point position = GetBounds(x, y).Center;
            gems.Add(new Gem(this, new Vector2(position.X, position.Y), type));

            return new Tile(null, TileCollision.Passable);
        }

Rectangle.CenterがVector2を返せば gems.Add(new Gem(this, GetBounds(x, y).Center, type)); と書けるんだがなあ。 まどろっこしい。 せめて (Vector2)(GetBounds(x, y).Center)とか書けると良いのだが。

クラスAnimationは

    class Animation
    {
        public Texture2D Texture
        {
            get { return texture; }
        }
        Texture2D texture;

        public float FrameTime
        {
            get { return frameTime; }
        }
        float frameTime;

        public bool IsLooping
        {
            get { return isLooping; }
        }
        bool isLooping;

        public Animation(Texture2D texture, float frameTime, bool isLooping)
        {
            this.texture = texture;
            this.frameTime = frameTime;
            this.isLooping = isLooping;
        }
    }

ではなく、

    class Animation
    {
        public readonly Texture2D Texture;
        public readonly float FrameTime;
        public readonly bool IsLooping;

        public Animation(Texture2D texture, float frameTime, bool isLooping)
        {
            Texture = texture;
            FrameTime = frameTime;
            IsLooping = isLooping;
        }
    }

と書けば済むのではないか。 まあ、大した違いは無いが。

プロパティって「クラス内部から見るとメソッドのように使えて、 クラスの外から見るとメンバー変数のように見える」 ものなんだな。かつ、内部と外部でのアクセス制御や隠蔽の制御もできる。 で、確かにそのように見事に使われている例もあるが、そうじゃない例もたくさんある。 コンストラクタでしか初期化しないものは public readonlyにすれば良いし、 コンストラクタ以外でもいろいろいじる必要があるものは { get; private set; } にすれば良いということでよいかと。 どうでも良いついでに言わせてもらえば、{ get; private set; }の方がpublic readonlyって感じで、 public readonlyはpublic write_once (or set_once) みたいな宣言にすりゃ良いのにとか思う。 わざわざプロパティにせず。