《VB2008从入门到精通(PDF格式英文版)》第112章


objects。Add(New Another()) 
For Each obj As Example In objects 
Console。WriteLine(〃Object value (〃 & obj。Value & 〃)〃) 
Next 
The bolded code illustrates how the collection object contains two instances of Example
and one instance of Another。 The code will pile; which misleads you into believing every
thing is fine。 If you try to run the application (either normally or in debug mode); you will see
something similar to the following: 
Unable to cast object of type "OneToManySamples。Another" to type
"OneToManySamples。Example"。 
So; should a collection contain multiple types? There are arguments for and against the
idea; but the problem is not the ability to mix types。 The problem is that you can mix types;
even if you don’t really intend to do that。
Using the For Each statement with mixed types will result in an exception; because for
each iteration; the object in the collection is cast to a type Example。 As the last item in the collec
tion is of type Another; the cast will fail; and an exception will be generated。 Collections before
2。0 could not enforce type consistency; and that was a problem。
Had you desired to mix types; the proper For Each loop would have been as follows: 
Dim objects As IList = new ArrayList() 
objects。Add(New Example With {。Value = 10}) 
objects。Add(New Example With {。Value = 20}) 
objects。Add(New Another()) 
For Each obj As Object In objects 
If TypeOf (obj) Is Example Then 
Dim example As Example = CType(obj; Example) 
Console。WriteLine(〃Object value (〃 & example。Value & 〃)〃) 
ElseIf TypeOf (obj) Is Another Then 
Console。WriteLine(〃This is another object〃) 
End If 
Next
…………………………………………………………Page 255……………………………………………………………
C HA P TE R 9 ■ L E AR N I N G A B O U T L I ST S; DE L E G AT E S ; AN D L A M B D A E X PR E SSI O N S 233 
The Problem of Value Types 
Another issue with pre…Visual Basic 2005 collections is that they have performance problems。
Consider the following code that manipulates value types。 
Dim objects As IList = New ArrayList() 
objects。Add(1) 
objects。Add(2) 
For Each val as Integer in objects 
Console。WriteLine(〃Value (〃 & val & 〃)〃) 
Next 
In the example; an ArrayList is again instantiated; but this time; the numbers 1 and 2 are
added to the collection。 Then; in the For Each statement; the integers are iterated。 The code
works; but there is a hidden performance hit。 The items added to the collection are value types;
which means you are manipulating stack…based memory。 
However; the definition of IList uses objects: 
Public Interface IIList 
Inherits ICollection; IEnumerable 
" Methods 
Function Add(ByVal value As Object) As Integer 
Sub Clear() 
Function Contains(ByVal value As Object) As Boolean 
Function IndexOf(ByVal value As Object) As Integer 
Sub Insert(ByVal index As Integer; ByVal value As Object) 
Sub Remove(ByVal value As Object) 
Sub RemoveAt(ByVal index As Integer) 
" Properties 
ReadOnly Property IsFixedSize() As Boolean 
ReadOnly Property IsReadOnly() As Boolean 
Property Item(ByVal index As Integer) As Object 
End Interface 
How IList is defined and how a value type is defined should raise alarms。 An object is a
reference type; and thus you have a conflict: IList stores reference types; but Integer is a value
type。
What’s happening is that the environment knows that there is a conflict and adds a
fix。 Don’t think of the fix as a hack; but as a way of solving a problem that all virtual machine
environments like need to address。 The environment uses the terms boxing and
unboxing to denote converting a value type into a reference type and then back again; respectively。 
To understand boxing and unboxing; let’s consider the context。 You are creating a list that
references value types。 The array is a reference type that is stored on the heap; but value types are
stored on the stack。 If you get the array to reference data on the stack; you will have a consistency
issue; since the stack changes。 Thus; you will need to move the memory from the stack to the
heap; but that would violate the principle behind value types。 The solution is the promise
of boxing and unboxing。
…………………………………………………………Page 256……………………………………………………………
234 CH AP T E R 9 ■ L E A R N IN G AB OU T L I ST S; D E L E G A T E S; A N D L A M B DA E X P R E S SI ON S
To illustrate what boxing does; I have written some code that is similar to the boxing of a
value type。 The difference is that my code is explicit and boxing is done automatically。 
Class ReferenceHeap
Public Value As Integer 
End Class 
。 。 。 
Public Sub Method()
Dim onStack As Integer = 1 
Dim onHeap As ReferenceHeap = New ReferenceHeap() With { 。Value = onStack } 
End Sub 
In the example; Method() declares a value…type variable named onStack; which is allocated
in the context of a method and is thus on the stack。 The type ReferenceHeap is a class; and thus
a reference type; and automatically all of its data is stored on the heap。 When the variable
onHeap is allocated and initialized; the value from onStack is copied to the heap and
小说推荐
返回首页返回目录