Re: Structures not behaving as value types
Richard Kucia <[email protected]> Mon, 25 Feb 2008 18:56:06 +0000
| Newsgroups | gmane.comp.windows.devel.dotnet.clr |
|---|---|
| Message-ID | <022520081856.25086.47C30F460009C48B000061FE22230682329B0A02D29B9B0EBF0E070C9A05069D@att.net> |
Option Explicit On
Option Strict On
Public Structure strFieldMask
Private Const K_BITS As Integer = 128
Private Const K_BITS_PER_ITEM As Integer = 32 ' 32 bits per Integer
Private Const UBOUND As Integer = (K_BITS - 1) \ 32 ' Number of items required
Private Const HIGH_ORDER As Integer = 1 << 31 ' High order bit of an integer
Private mMask() As Integer ' Array of words with the bits
#Region "Accessors"
Private Property Mask(ByVal I As Integer) As Integer
Get
If mMask Is Nothing OrElse mMask.Length = 0 Then ReDim mMask(UBOUND)
Return mMask(I)
End Get
Set(ByVal value As Integer)
If mMask Is Nothing OrElse mMask.Length = 0 Then ReDim mMask(UBOUND)
mMask(I) = value
End Set
End Property
Public ReadOnly Property AsString() As String
Get
Return Me.ToString()
End Get
End Property
#End Region
#Region "Operators"
Public Shared Operator =(ByVal Operand1 As strFieldMask, ByVal Operand2 As strFieldMask) As Boolean
For I As Integer = 0 To UBOUND
If Operand1.Mask(I) <> Operand2.Mask(I) Then Return False
Next
Return True
End Operator
Public Shared Operator <>(ByVal Operand1 As strFieldMask, ByVal Operand2 As strFieldMask) As Boolean
Return Not (Operand1 = Operand2)
End Operator
Public Shared Operator And(ByVal Operand1 As strFieldMask, ByVal Operand2 As strFieldMask) As strFieldMask
Dim Result As New strFieldMask
For I As Integer = 0 To UBOUND
Result.Mask(I) = Operand1.Mask(I) And Operand2.Mask(I)
Next
Return Result
End Operator
Public Shared Operator Or(ByVal Operand1 As strFieldMask, ByVal Operand2 As strFieldMask) As strFieldMask
Dim Result As New strFieldMask
For I As Integer = 0 To UBOUND
Result.Mask(I) = Operand1.Mask(I) Or Operand2.Mask(I)
Next
Return Result
End Operator
Public Shared Operator Not(ByVal Operand As strFieldMask) As strFieldMask
Dim Result As New strFieldMask
For I As Integer = 0 To UBOUND
Result.Mask(I) = Not Operand.Mask(I)
Next
Return Result
End Operator
Public Shared Operator <<(ByVal Operand As strFieldMask, ByVal Bits As Integer) As strFieldMask
Dim Result As strFieldMask
Dim BitCrossing As Integer
' Brute force method: shift one bit at a time
Result = Operand
For Bit As Integer = 1 To Bits
For I As Integer = UBOUND To 0 Step -1 ' From MS to LS
If I > 0 Then ' If a lower bit could be promoted...
If (Operand.Mask(I - 1) And HIGH_ORDER) <> 0 Then ' ...then capture the bit that crosses the word
BitCrossing = 1
Else
BitCrossing = 0
End If
Else
BitCrossing = 0 ' ...else this is the LSW -- shift-in a 0
End If
Result.Mask(I) = (Result.Mask(I) << 1) Or BitCrossing
Next
Next
Return Result
End Operator
#End Region
#Region "Other Functions and Methods"
Public Property Bit(ByVal BitNumber As Integer) As Boolean
Get
Const One As Integer = 1
Dim I As Integer
Dim TheBit As Integer
I = BitNumber \ K_BITS_PER_ITEM
TheBit = Mask(I) And (One << (BitNumber Mod K_BITS_PER_ITEM))
Return (TheBit <> 0)
End Get
Set(ByVal State As Boolean)
If State Then
SetBit(BitNumber)
Else
ResetBit(BitNumber)
End If
End Set
End Property
Public Sub SetBit(ByVal BitNumber As Integer)
Const One As Integer = 1
Dim I As Integer
I = BitNumber \ K_BITS_PER_ITEM
Mask(I) = Mask(I) Or (One << (BitNumber Mod K_BITS_PER_ITEM))
End Sub
Public Sub ResetBit(ByVal BitNumber As Integer)
Const One As Integer = 1
Dim I As Integer
I = BitNumber \ K_BITS_PER_ITEM
Mask(I) = Mask(I) And Not (One << (BitNumber Mod K_BITS_PER_ITEM))
End Sub
Public Sub Zero()
For I As Integer = 0 To UBOUND
Mask(I) = 0
Next
End Sub
Public ReadOnly Property IsZero() As Boolean
Get
For I As Integer = 0 To UBOUND
If Mask(I) <> 0 Then Return False
Next
Return True
End Get
End Property
#End Region
#Region "ToString"
Public Overrides Function ToString() As String
Const BYTEMASK As Integer = &HFF
Dim str As System.Text.StringBuilder
Dim B(K_BITS \ 8 - 1) As Byte
Dim N As Integer
Dim Word As Integer
N = 0
For I As Integer = 0 To UBOUND
Word = Mask(I)
For ByteNumber As Integer = 0 To K_BITS_PER_ITEM \ 8 - 1
B(N) = Convert.ToByte(Word And BYTEMASK)
Word = Word >> 8 ' Put the next byte into the low-order position
N += 1
Next
Next
str = New System.Text.StringBuilder
For N = B.Length - 1 To 0 Step -1
str.AppendFormat("{0:X2} ", B(N))
Next
Return str.ToString
End Function
#End Region
End Structure
-------------- Original message from Greg Young <[email protected]>: --------------
> Can you put up your code?
>
> On Mon, Feb 25, 2008 at 10:44 AM, Richard Kucia wrote:
> > Well, in fact it does. The mask structure contains one array of N 32-bit
> integers to hold the bits. Each time any function or property of the mask is
> invoked, that code tests the array to see if it is (nothing), and Redim's it.
> >
> > So that explains it. The formula mentioned below takes the most recently used
> mask structure and shifts it left 1 bit. So each request for another mask is
> obviously getting the same object reference, and when the bit-shift occurs, it
> effectively occurs in every mask structure, since they are all referencing the
> same array.
> >
> > So what is the correct way to handle this? I want each structure to have its
> own independent array of N 32-bit integers.
> >
> > Rick
> > -------------- Original message from Matthew Wills
> : --------------
> >
> >
> >
> > > Richard,
> > >
> > > Show us the code for strFieldMask. I would bet you are using some reference
> > > types in it.
> > >
> > > Seeya
> > > Matthew Wills | Solution Designer | Adviser Tools and Services | Financial
> > > Planning and Third Party | NAB Technology
> > >
> > > Phone: 02 9376 4029 | Mobile: 0435 002 520 | Email:
> > > [email protected]
> > >
> > >
> > >
> > >
> > > Richard Kucia
> > >
> >
> >
> > > To
> > > [email protected]
> > > cc
> > >
> > > Subject
> > > [DOTNET-CLR] Structures not
> > > behaving as value types
> > >
> > > I have a VB.Net declaration of a structure strFieldMask. The intended
> > > purpose is to store a bunch of bits, like a bit vector. The structure also
> > > has operator declarations for =, <>, And, Or, Not and <<, plus some other
> > > methods for bit manipulation.
> > >
> > > The problem is that variables of type strFieldMask seem to behave as
> > > though there was a singleton strFieldMask and all instances shared it.
> > >
> > > Consider this:
> > >
> > > Dim Mask1 as strFieldMask
> > > Dim Mask2 as strFieldMask
> > >
> > > Mask1 = (formula for computing the next unused mask value)
> > > Debug.WriteLine(Mask1.ToString))
> > > Mask2 = (same formula)
> > > Debug.WriteLine(Mask1.ToString)) ' Yes, Mask1, not Mask2
> > >
> > > The result from the first WriteLine might be "0x10" and the result from
> > > the second WriteLine might be "0x20".
> > >
> > > I've successfully used structures before, but this is the first time I've
> > > tried overloading the operators. Has that caused the behavior I'm seeing?
> > >
> > > Thanks.
> > >
> > >
> > >
> > > National Australia Bank Ltd - ABN 12 004 044 937
> > > This email may contain confidential information. If you are not the
> intended
> > > recipient, please immediately notify us at [email protected] or by
> replying
> > > to
> > > the sender, and then destroy all copies of this email. Except where this
> email
> > > indicates otherwise, views expressed in this email are those of the sender
> and
> > > not
> > > of National Australia Bank Ltd. Advice in this email does not take account
> of
> > > your
> > > objectives, financial situation, or needs. It is important for you to
> consider
> > > these
> > > matters and, if the e-mail refers to a product(s), you should read the
> relevant
> > > Product Disclosure Statement(s)/other disclosure document(s) before making
> any
> > > decisions. If you do not want email marketing from us in future, forward
> this
> > > email
> > > with "unsubscribe" in the subject line to [email protected] in
> order to
> > > stop marketing emails from this sender. National Australia Bank Ltd does
> not
> > > represent that this email is free of errors, viruses or interference.
> > >
> > > ===================================
> > > This list is hosted by DevelopMentor(R) http://www.develop.com
> > >
> > > View archives and manage your subscription(s) at http://discuss.develop.com
> >
> > ===================================
> > This list is hosted by DevelopMentor(R) http://www.develop.com
> >
> > View archives and manage your subscription(s) at http://discuss.develop.com
> >
>
>
>
> --
> Studying for the Turing test
>
> ===================================
> This list is hosted by DevelopMentorĀ® http://www.develop.com
>
> View archives and manage your subscription(s) at http://discuss.develop.com
===================================
This list is hosted by DevelopMentorĀ® http://www.develop.com
View archives and manage your subscription(s) at http://discuss.develop.com