按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
sheetAverage。AssignCellCalculation(row; 1; _
Function(worksheet As IWorksheet(Of Double); cellRow As Integer; _
cellCol As Integer)
(worksheet。GetCellState(cellRow; 0) _
worksheet。Calculate(items。Length; 0)))
Next row
The number of cell…state calculations depends on the count of numbers in items。 Each cell
calculation is assigned a locally declared lambda expression; meaning that the lambda expres
sions of all cell states will be identical and share the same state。 The only shared variable is
items。Length。 All the lambda expressions expect the same length; and so it is acceptable to
share this variable。 The average difference is calculated by calculating the average and then
subtracting it from the worksheet cell item value that is in the zeroth column。
Finally; when everything is assigned; you can call the worksheet。Calculate() method to
calculate the average and difference from the average。
sheetAverage。Calculate()
Console。WriteLine(sheetAverage。ToString())
Understanding Why the Calculation Worked
The cell calculations work because the spreadsheet has the ability to track what has been calculated
and what has not been calculated。 In a typical spreadsheet; you can change one cell in a sheet
and have everything magically recalculate。 There is no such feature for this spreadsheet。 However;
this simpler spreadsheet version can make sure that when there are dependencies; they are not
calculated multiple times。
Look back at the source code to calculate the difference between the average and a number。
The only reason the calculation worked is that the cell that contained the average was called
using the Calculate() method。 Had the GetCellState() method been used; the average might
not have been calculated; and thus the difference calculation would have been corrupted。
But having each and every cell calculate the average whenever a small change is made is a
waste of resources; since the change might not affect a cell that is recalculated。 To avoid this;
built into the spreadsheet is a version…control mechanism that calculates a cell to the latest
version。 Then; if another calculation is called with the same version number; the value is retrieved
from the cell state。 The following is the code from Worksheet(Of BaseType) that manages the
version number。
Public Function Calculate(ByVal row As Integer; ByVal col As Integer) As BaseType _
Implements IWorksheet(Of BaseType)。Calculate
If (CurrVersion 》 CalculationVersion(row; col)) Then
CellState(row; col) = Cells(row; col)(Me; row; col)
CalculationVersion(row; col) = CurrVersion
End If
Return CellState(row; col)
End Function
…………………………………………………………Page 333……………………………………………………………
CH AP T E R 1 1 ■ L E A R N IN G AB O U T 。 N E T G E N E R I CS 311
Public Sub Calculate() Implements IWorksheet(Of BaseType)。Calculate
CurrVersion += 1
Dim row As Integer
For row = 0 To Cells。GetLength(0) 1
Dim col As Integer
For col = 0 To Cells。GetLength(1) 1
If Cells(row; col) IsNot Nothing Then
Calculate(row; col)
End If
Next col
Next row
End Sub
Calling the method Calculate() without parameters indicates a desire to recalculate the
entire spreadsheet。 In the implementation of Calculate(); the variable CurrVersion; which
represents the version number of the current calculation; is incremented。 Then each cell is iter
ated; and if it exists; the individual cell form of Calculate() (Calculate() with the parameters row
and col) is called。 In the individual cell form of Calculate(); a check is made to see if the calcu
lation version number of the cell is the latest of the spreadsheet; if not; the cell’s lambda expression
is called。 After the new CellState has been assigned; the cell…state version number is incre
mented; and the cell state is returned。
■Note The calculation of the spreadsheet is nothing earth…shattering; and you might be tempted to argue
it is irrelevant to the scope of the book。 In fact; the calculation and its side effects are of major relevance。 With
lambda expressions; you have a form of asynchronous processing; very much like a spreadsheet。 The cell
calculations of the spreadsheet do not know when they will be called; and they cannot make assumptions
about the state。 Thus; when a lambda expression is created; the state at the time of the lambda expression
may not be the same as when the lambda expression is executed。 If you are not acutely aware of this potential
pitfall; you could have some major bugs in your code。
The Important Stuff to Remember
In this chapter; you learned how to use generics and also expanded your knowledge of
lambda expressions。 The main items to remember are as follows:
o generics code can use generics; or it can be code that provides types based on
generics。
o Performance and type…safe characteristics are primary reasons for using generics。
o You can use generics at the type level or at the method level。 Using generics
at the type level implies concretizing the type when the type is instantiated。 Using
generics at the method level implies concretizing the type when the method is called。
o Lambda expressions may be shared state or individual state; depending on how they are
declared and manipulated。
…………………………………………………………Page 334……………………………………………………………
312 CH AP T E R 1 1 ■ L E A R N I N G A B OU T 。 N E T G E N E R I CS
o For plex types; you should always implement ToString() as a way of figuring out the
state of an instance。
o Lambda expressions act asynchronously。 When you use them; remember to not make
assumptions of a particular state。
Some Things for You to Do
The following are some exercises that allow you to apply what you’ve learned so far。
1。 The Worksheet(Of BaseType) class always requires you to dimension the fixed…cell array
ahead of time。 Change this code so that the number of rows and columns can change
dynamically。 Remember that the focus is on performance; and the fastest approach is a
fixed…dimension array。
2。 The average calculation knows how many items there are by the row number。 Rewrite
the average calculation code so that the user of the average code does not need to deal
with the plexities of adding more elements; moving the cell calculation; and so on。
3。 The methods Calculate() and GetCellState() seem to do the same thing。 So; is there a
need to have separate methods? Answer the question; and then make any necessary
changes to the source code based on your answer。
…………………………………………………………Page 335……………………………………………………………
C H A P T E R 1 2
■ ■ ■
Learning About
Application Configuration
and Dynamic Loading
All of the examples in the preceding chapters have demonstrated how to use an application
with a specific ponent。 You knew which type to instantiate; which interface to use; and
which project to