Created
February 11, 2015 05:20
-
-
Save ufcpp/ea855492e206c300ec6d to your computer and use it in GitHub Desktop.
値セマンティクスを持つクラス。タプルとレコード再考
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Point の実際の値を持つ構造体。 | |
// 現状の C# だと自分で実際にこういう型定義を書く必要があるけども、タプルにできるのでは。 | |
struct PointValue | |
{ | |
public int X; | |
public int Y; | |
} | |
// 値セマンティクスを持つ immutable クラス | |
// レコード型の実装はこうあるべきだろうという内容。 | |
// ここでいう値セマンティクス(value semantics)は、全メンバー比較で Equals、全メンバーのハッシュ値から GetHashCode 計算できるもののこと。 | |
class Point | |
{ | |
// 唯一の構造体メンバーに readonly を付けているので immutable。 | |
// タプルが入るのであれば、public readonly (int X, int Y) Value; でいいはず。 | |
// Point p に対して (var x, var y) = p; で、(var x, var y) = p.Value; の意味に解釈するのもよさそう。 | |
public readonly PointValue Value; | |
// 外から mutable な型で値をもらう。いわゆる「ビルダー パターン」。 | |
// PointValue をタプルにするのなら、スプラッティングが効いて、new Point(x, y) とも書けるはず。 | |
// 簡易構文として、new Point { X = 1, Y = 2 } で、new Point(new PointValue { X = 1, Y = 2 }) の意味に解釈するのもよさそう。 | |
public Point(PointValue value) { Value = value; } | |
// Value に処理を丸投げ | |
public int X => Value.X; | |
public int Y => Value.Y; | |
public override int GetHashCode() => Value.GetHashCode(); | |
public override bool Equals(object obj) => (obj as Point)?.Value.Equals(Value) ?? false; | |
// 値書き換え(immutable なので別のインスタンスを作る)用の "wither" (GetX, SetX みたいなのを getter/setter というように、WithX をこう言う) | |
// p.Value { X = 1 } みたいに、new するとき以外でもオブジェクト初期化子を使えると、wither 書くのが楽になるはず。 | |
// Point WithX(int x) => new Point(Value { X = x }); | |
// あと、var q = p { X = 1 }; みたいなので new Point(Value { X = 1 }) の意味に解釈するのもよさそう。 | |
// これなら、自前の wither 定義要らない。 | |
public Point WithX(int x) { var v = Value; v.X = x; return new Point(v); } | |
public Point WithY(int y) { var v = Value; v.Y = y; return new Point(v); } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment