嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
VB2008貫秘壇欺娼宥(PDF鯉塀哂猟井)-及47何蛍
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何! 泌惚云慕短嗤堋響頼���誅卒亮茂�俊彭堋響��辛聞喘貧圭 "辺茄欺厘議箝誓匂" 孔嬬 才 "紗秘慕禰" 孔嬬��
would instantiate the delegate with the method and call Iterate�┌��察�as follows�此�
Iterator。Iterate��lst�察�New ProcessValue��ProcessRunningTotal����
。 。 。
Iterator。Iterate��lst�察�New ProcessValue��ProcessMaximumValue����
The code that wants to automatically iterate code must provide only a delegate imple
mentation。
Implementing Methods That Match the Delegate
Implementing methods that match a delegate is straightforward in that you need to declare
only a method in a class that has the same method signature。 This can be implemented using
a shared method or an instance method�察�it does not matter。 The following code demonstrates
methods that match the ProcessValue delegate¨s signature using both types of methods。
Class DelegateImplementations
Private Sub InstanceProcess��ByVal value As Integer��
End Sub
Private Shared Sub SharedProcess��ByVal value As Integer��
End Sub
End Class
In the example�察�the InstanceProcess�┌� and SharedProcess�┌� methods match the signature
of the delegate ProcessValue。 If you have two delegates with identical parameter and return
type signatures�察�then a method with the same signature can be used for either delegate definition。
The following shows how to have the methods be recognized as a delegate。
´´´´´´´´´´´´´´´´´´´´´´Page 264´´´´´´´´´´´´´´´´´´´´´´´
242 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
Dim instanceMethod As New ProcessValue��AddressOf InstanceProcess��
Dim sharedMethod As New ProcessValue��AddressOf SharedProcess��
These two lines instantiate the delegate using the New keyword�察�and each instantiation has
a single constructor parameter�察�which is the method to associate with the delegate instance。
Now let¨s look at the running total and maximum value example and see the methods that
will be wrapped up by delegates。
Module Tests
Private _maxValue As Integer
Private _runningTotal As Integer
Private Sub ProcessMaximumValue��ByVal value As Integer��
If ��value 〃 Tests。_maxValue�� Then
_maxValue = value
End If
End Sub
Private Sub ProcessRunningTotal��ByVal value As Integer��
_runningTotal = _runningTotal �� value
End Sub
End Module
The ProcessMaximumValue�┌� and ProcessRunningTotal�┌� methods both have the same
signatures as ProcessValue�察�and therefore are delegate candidates。 In each delegate implemen
tation�察�the running total is calculated or the maximum value is found。 The following code uses
the delegates。
Public Sub RunAll�┌�
Dim lst As New List��Of Integer���┌�
lst。Add��1��
lst。Add��2��
lst。Add��3��
lst。Add��4��
_runningTotal = 0
Iterator。Iterate��lst�察�New ProcessValue��AddressOf ProcessRunningTotal����
Console。WriteLine�┌─�Running total is �──�& _runningTotal & ;��;����
_maxValue = Integer。MinValue
Iterator。Iterate��lst�察�New ProcessValue��AddressOf ProcessMaximumValue����
Console。WriteLine�┌─�Maximum value is �──�& _maxValue & ;��;����
End Sub
In the example�察�the RunAll�┌� method instantiates and assigns lst。 Then to iterate the indi
vidual elements�察�the Iterator。Iterate�┌� method is called with lst and the
ProcessRunningTotal�┌� method。 After having calculated and presented the running total�察�the
maximum value is calculated and displayed。
´´´´´´´´´´´´´´´´´´´´´´Page 265´´´´´´´´´´´´´´´´´´´´´´´
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 243
The delegate solution is more pact than the previous abstract base class solution。 The
big advantage is the ability to solve a problem using a smaller�察�piecemeal approach。 It is not
hard to implement a delegate�察�and it is not hard to use a delegate。
Understanding Lambda Expressions
Lambda expressions are an extension of delegates�察�but solve a specific problem。 Let¨s take the
example of calculating sales tax。 Sales tax in general is a simple calculation in that you take the
total amount�察�multiply it by the sales tax�察�and add the result to the amount。 This gives you the
total a customer must pay。 Calculating a sales tax is not difficult�察�but it is something that would
be nice to encapsulate into a small piece of functionality。 Thus�察�calculating sales tax is an excel
lent use of lambda expressions。
A lambda expression is declared as a Function that has a single expression as a body。 Following
is the declaration of a lambda expression。
Dim calculate = Function��tax As Double�察�amount As Double�� ��tax * amount�� �� amount
The lambda expression is declared as a function without a return type。 The code after the
brackets is a single expression that uses the parameters to perform some action。 In the example�察 �
that single expression is the calculation of the sales tax that is added to the amount to generate
a new total。
The lambda expression could be used as follows�此�
Console。WriteLine�─�Tax �──�& calculate��0。1�察�100�� & ;��;��
The calculate lambda expression is called with two numbers that are of type Double�察�which
generates an expression similar to this�此�
Function sdfsdfsdf��tax As Double�察�amount As Double�� As Double
Return ��tax * amount�� �� amount
End Function
Notice a return type of Double is declared in the generated code。 The piler did this by
inferring from the code。
Single´expression lambda expressions have some use�察�but their real value is in the ability
to create a closure that establishes a context。 A closure holds the evaluated lambda expression
with its bound variables for other functions to use�察�which is how the context is established。
Let¨s say that we are going to calculate the sales tax for a particular place like Quebec�察 �
Canada。 The sales tax there is 15�ィ察�and thus when using the lambda expression�察�we abstract
and create code similar to the following。
Console。WriteLine�─�Tax �──�& calculate��SalesTax。Quebec�察�100。0�� & ;��;��
The value for the sales tax is held in the property SalesTax。Quebec�察�and whenever we use
the lambda expression�察�we need to specify the property。
With lambda expressions and closure�察�you have the ability to save a context。 For starters�察 �
let¨s redefine the lambda expression to have only a single parameter�此�
Function��amount As Double�� ��tax * amount�� �� amount
´´´´´´´´´´´´´´´´´´´´´´Page 266´´´´´´´´´´´´´´´´´´´´´´´
244 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
Notice that the lambda expression still uses the tax rate in its calculation。 This is where context
es in。 We can save the context of a certain tax rate and then use the lambda expression in that
context。 To do so�察�we need a lambda expression that returns our new one´parameter lambda
expression�此�
Function��tax As Double�� Function��amount As Double�� ��tax * amount�� �� amount
We can set the tax rate with the first lambda expression�察�and then call the second to calcu
late the tax�此�
Dim prepareTax =
Function��tax As Double�� Function��amount As Double�� ��tax * amount�� �� amount
Dim doQuebec = prepareTax��0。1��
Console。WriteLine��doQuebec��100����
The call to prepareTax defines doQuebec as prepareTax��0。1�� and sets the tax variable in the
context of doQuebec。 Now when we call doQuebec�察�we can calculate the total amount without
ever needing to specify the tax rate again。
Lambda expressions allow only a single expression。 If you want to implement a lambda
expression that should make a decision�察�you have a problem。 To solve this problem�察�you can
use an If statement variation that is like a function。 Imagine a country where the applicable
sales tax depends on the amount you purchased。 This logic could be implemented using a
closure and ternary If statement�察�as follows�此�
Dim setMinimumSalesTax = Function��minimumSalesTax As Double��
Function��amount As Double��
If��amount 〃 minimumSalesTax�察�
��0。15 * amount�� �� amount��_
��0。1 * amount�� �� amount��
Dim calculateTotal = setMinimumSalesTax��100��
Console。WriteLine��calculateTotal��80����
Console。WriteLine��calculateTotal��500����
The ternary If is a function that has three parameters。 The first parameter is the expres
sion you want to test。 Typically�察�whatever you would write in a regular If block�察�you would
write as the first parameter。 In the example�察�it is a test of whether or not the bought amount
is greater than a minimum amount。 The second parameter is an expression that is executed
whenever the first parameter results in a True value。 The third parameter executes if the first
parameter results in a False value。
Another variation of the If function is a two´parameter version that can be used to test
whether or not an object has a value of Nothing�察�as follows�此�
Dim cleanUpList = Function��defaultObject As Object��_
Function��objToTest As Object�� If��objToTest�察�defaultObject��
´´´´´´´´´´´´´´´´´´´´´´Page 267´´´´´´´´´´´´´´´´´´´´´´´
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 245
The implementation of the lambda expression has an If with two parameters。 The first
parameter is the object to test for Nothing�察�and the second parameter represents the expression
to execute if the object is Nothing。
Learning More About Collection Types
In the beginning of this chapter�察�I talked about the different collection types�察�but not how to use
them。 This section presents examples of using the types。
Using a Plain´Vanilla List
A plain´vanilla list is a list of specific types such as Integer�察�Double�察�or some other object type。
Instantiate the list as follows�此�
Dim lst As List��Of MyType�� = New List��Of MyType���┌�
The default type List is used for most of your coding situations�察�but if you are adding and
removing elements frequently�察�the following code is better。
Dim lst As IList��Of MyType�� = New LinkedList��Of MyType���┌�
The type LinkedList implements the logic that was presented in the previous chapter�察 �
whereas List manipulates a fixed´length array。 LinkedList has a downside in that it does not
support the IList interface�察�and the sample code will not pile。 Thus�察�to make the code
work�察�you would need to use ICollection�此�
Dim lst As ICollection��Of MyType�� = New LinkedList��Of MyType���┌�
Add an element to IList as follows�此�
lst。Add��New MyType�┌���
To add elements to your list according to an order�察�use the following form ��note that
ICollection doesn¨t have this method��。
lst。Insert��0�察�New MyType�┌���
This adds an element to the front of the list。 If you are adding elements at the beginning of
the list or somewhere in the list�察�it is better to use the LinkedList type�察�as it is more efficient。
Using the class List incurs an array copy resource penalty。
You can also add one list to another�此�
Dim lst As List��Of MyType�� = New List��Of MyType���┌�
Dim lstToBeAdded As List��Of MyType��
lst。AddRange��lstToBeAdded��
lst。InsertRange��0�察�lstToBeAdded��
The AddRange�┌� method is used to append the list lstToBeAdded to lst。 The InsertRange�┌�
method inserts all of the elements in lstToBeAdded to the front of the list lst。
´´´´´´´´´´´´´´´´´´´´´´Page 268´´´´´´´´´´´´´´´´´´´´´´´
246 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
Delete an element from the list like this�此�
lst。Remove��existingMyType��
The Remove�┌� method expects an instance of a type to remove from the list。
To delete a particular element at a particular index�察�use the following form。
lst。RemoveAt��0��
This code would remove the element at the front of the list。
Using a Key/Value Pair List
A key/value pair list is a list that has a cross´reference。 It is like a dictionary where you have
a word and associated meaning。 In puting terms�察�the word is a type and its definition is
another type。 The word is a key and the definition is a value。 A key/value pair definition would
be as follows�察�using the IDictionary interface and Dictionary class。
Dim dictionary As IDictionary��Of String�察�Object�� = _
New Dictionary��Of String�察�Object���┌�
You could also use SortedDictionary�察�but that implies the elements within the list are sorted。
To add values to the dictionary�察�use the Add�┌� method�此�
dictionary。Add�─�List;�察�lst��
dictionary。Add�─�List To Be Added;�察�lstToBeAdded��
When working with IDictionary objects�察�you might want to know whether or not a key is
available。 The following code is used to verify if a key exists。
If dictionary。ContainsKey�─�List;�� Then
。 。 。
End If
If you want to iterate the keys�察�use this form�此�
For Each key As String In dictionary。Keys
Next
Iterate the values as follows�此�
For Each value As Object In dictionary。Values
Next
Using a Stack
A Stack is a special list that behaves like a stack of paper on a table。 When you add three items
on the Stack�察�the
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��