[英]Value semantics in c# struct vs tuple
所以我在C#中邁出了第一步,正在制作一個簡單的瓷磚拼圖。 當我模擬瓷磚的位置時,我想要有價值語義。 因此,據我所知,基本上有兩種方法可以實現這一點,包括結構或元組。
在Tuple的情況下,我的代碼如下所示:
public class TilePosition : Tuple<int,int> { public int HComponent{get { return Item1; }} public int VComponent{get { return Item2; }} public TilePosition(int horizontalPosition, int verticalPosition) : base(horizontalPosition, verticalPosition) { } }
struct解決方案看起來像這樣:
public struct TilePosition { private readonly int hComponent; private readonly int vComponent; public int HComponent { get { return hComponent; } } public int VComponent { get { return vComponent; } } public TilePosition(int hComponent, int vComponent) { this.hComponent = hComponent; this.vComponent = vComponent; } public static bool operator ==(TilePosition position1, TilePosition position2) { return position1.Equals(position2); } public static bool operator !=(TilePosition position1, TilePosition position2) { return !(position1 == position2); } }
元組是簡潔的,但它暴露了Item1
和Item2
,這會在公共API中混淆,即使我已經在它們周圍添加了H和V組件屬性。
結構需要更多的代碼,我得到一個編譯器警告我應該如何重寫Equals和GetHashCode,因為我重寫==
和!=
,但如果我這樣做,我沒有從使用結構(從語義和句法觀點)因為它與傳統的類完全相同。
除了沒有Item屬性的噪聲之外,在子類化元組上使用struc還有什么好處嗎?
我的解決方案是否都會以我預期的方式運行,或者我應該注意哪些細微差別?
( IEquatable<TilePosition>
在兩種情況下都可以實現IEquatable<TilePosition>
- 特別是在結構案例中,以避免裝箱。)
除了沒有Item屬性的噪聲之外,在子類化元組上使用struc還有什么好處嗎?
鑒於它是不可變的,在這兩種情況下,你在兩種情況下都有大致“價值語義”,但仍然存在差異......
null
是一個有效值; 在結構類型版本中你需要使用TilePosition?
表示可能缺席的值 new TilePosition()
是有效的,並且兩個字段的值都為0(這將是默認值,例如對於字段和數組元素) Tuple<,>
代碼一起使用,而結構類型顯然不是這種情況。 ==
的含義在兩種類型之間會有所不同。 即使你在類類型中重載==
,調用者仍然可能只是比較引用。 在結構案例中,您仍然可以最終比較盒裝引用,無益。 當然,這些只是差異 - 它們是否算作一種方法的好處 ,另一種取決於您的要求。
如何使用鋸齒狀數組並在每個字段上持有一個項目。 這將更緊密地遵循瓷磚拼圖:
移動瓷磚很容易,例如
if (fields[x, y] = null) { fields[x, y] = fields[oldX, oldY]; fields[oldX, oldY] = null; }
你最好的辦法就是把它做好並投入所有的工作。 如果你想要一個結構而不是一個類(可能適合你),這里有一個示例實現:
public struct TilePosition: IEquatable<TilePosition>
{
public TilePosition(int horizontalPosition, int verticalPosition)
{
_x = horizontalPosition;
_y = verticalPosition;
}
public int HComponent
{
get
{
return _x;
}
}
public int VComponent
{
get
{
return _y;
}
}
public static bool operator == (TilePosition lhs, TilePosition rhs)
{
return lhs.Equals(rhs);
}
public static bool operator != (TilePosition lhs, TilePosition rhs)
{
return !lhs.Equals(rhs);
}
public bool Equals(TilePosition other)
{
return (_x == other._x) && (_y == other._y);
}
public override bool Equals(object obj)
{
return obj is TilePosition && Equals((TilePosition)obj);
}
public override int GetHashCode()
{
unchecked
{
return (_x*397) ^ _y;
}
}
private readonly int _x;
private readonly int _y;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.