I\'m writing a game that has a huge 2D array of \"cells\". A cell takes only 3 bytes. I also have a class called CellMap, which contains the 2D array as a private field, and pro
Eric Lippert's approach is good, but I would suggest using a base class rather than an interface for the indirect accessor. The following program demonstrates a class which acts like a sparse array of points. Provided that one never persists any item of type PointRef(*), things should work beautifully. Saying:
MyPointHolder(123) = somePoint
or
MyPointHolder(123).thePoint = somePoint
will both create a temporary pointRef object (a pointRef.onePoint in one case; a pointHolder.IndexedPointRef in the other) but the widening typecasts work to maintain value semantics. Of course, things would have been much easier if (1) methods on value types could be marked as mutators, and (2) writing a field of a structure accessed via property would could automatically read the property, edit the temporary structure, and write it back. The approach used here works, though alas I don't know any way to make it generic.
(*) Items of type PointRef should only be returned by properties, and should never be stored in a variable or used as parameters to anything other than a setter property which will convert to a Point.
MustInherit Class PointRef Public MustOverride Property thePoint() As Point Public Property X() As Integer Get Return thePoint.X End Get Set(ByVal value As Integer) Dim mypoint As Point = thePoint mypoint.X = value thePoint = mypoint End Set End Property Public Property Y() As Integer Get Return thePoint.X End Get Set(ByVal value As Integer) Dim mypoint As Point = thePoint mypoint.Y = value thePoint = mypoint End Set End Property Public Shared Widening Operator CType(ByVal val As Point) As PointRef Return New onePoint(val) End Operator Public Shared Widening Operator CType(ByVal val As PointRef) As Point Return val.thePoint End Operator Private Class onePoint Inherits PointRef Dim myPoint As Point Sub New(ByVal pt As Point) myPoint = pt End Sub Public Overrides Property thePoint() As System.Drawing.Point Get Return myPoint End Get Set(ByVal value As System.Drawing.Point) myPoint = value End Set End Property End Class End Class Class pointHolder Dim myPoints As New Dictionary(Of Integer, Point) Private Class IndexedPointRef Inherits PointRef Dim ref As pointHolder Dim index As Integer Sub New(ByVal ref As pointHolder, ByVal index As Integer) Me.ref = ref Me.index = index End Sub Public Overrides Property thePoint() As System.Drawing.Point Get Dim mypoint As New Point(0, 0) ref.myPoints.TryGetValue(index, mypoint) Return mypoint End Get Set(ByVal value As System.Drawing.Point) ref.myPoints(index) = value End Set End Property End Class Default Public Property item(ByVal index As Integer) As PointRef Get Return New IndexedPointRef(Me, index) End Get Set(ByVal value As PointRef) myPoints(index) = value.thePoint End Set End Property Shared Sub test() Dim theH1, theH2 As New pointHolder theH1(5).X = 9 theH1(9).Y = 20 theH2(12).X = theH1(9).Y theH1(20) = theH2(12) theH2(12).Y = 6 Dim h5, h9, h12, h20 As Point h5 = theH1(5) h9 = theH1(9) h12 = theH2(12) h20 = theH1(20) End Sub End Class