按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
Private Cells As Func(Of IWorksheet(Of BaseType); Integer; Integer; BaseType)(;)
Private CellState As BaseType(;)
Private ColCells As Func(Of IWorksheet(Of BaseType); Integer; Integer; BaseType)()
The data member CellState contains the state of the worksheet cell; and its type is BaseType;
meaning that the type of the worksheet cell is whatever BaseType is declared as。 The data members
Cells and ColCells are declared as lambda expression references; where there are three param
eters and a return value。
Before I continue with the lambda expression explanation; I want to shift focus to illustrate
a problem。 We are going to play a game of what animal am I; where we’ll use lambda expressions
in conjunction with a closure。 The idea is to store the identifier of the animal in a closure and
then return it when it’s requested。
…………………………………………………………Page 325……………………………………………………………
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 303
Dim animals(1) As Func(Of String)
Dim animal As String
animal = 〃cow〃
animals(0) = Function() animal
animal = 〃horse〃
animals(1) = Function() animal
For Each callAnimal In animals
Console。Write (〃(〃 & callAnimal() & 〃)〃)
Next
The example creates an array of lambda expressions (animals) where space for two lambda
expressions is allocated。 The individual lambda expressions will reference a variable animal;
which contains the animal of the lambda expression。 In the code; the lambda expressions are
assigned when the state of animal changes from cow to horse。
Let’s say you run the code; and Console。WriteLine() generates its output。 What do you
think the animals will be? Do you expect cow and horse; respectively? Here’s the output:
(horse) (horse)
The generated output is not what you would expect。 This demonstrates that lambda expres
sions are stateless。 Yet in earlier explanations of lambda expressions and closures; I said that
variables can be stored in lambda expressions。 Since animal is a value type; you would expect
two copies of animal; right? Wrong。
Closures do work; and variable state is kept across lambda expressions。 The mistake in this
code is that the same variable is referenced by two lambda expressions。 Thus; when the two
lambda expressions execute; they will reference the same animal; which was last assigned to be
a horse。
The code that solves the problem uses two unique variables; as follows:
Dim animals(1) As Func(Of String)
Dim animal1 = 〃cow〃
animals(0) = Function() animal1
Dim animal2 = 〃horse〃
animals(1) = Function() animal2
For Each callAnimal In animals
Console。WriteLine(callAnimal())
Next
…………………………………………………………Page 326……………………………………………………………
304 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
This time when you run the code; you get the following output。
cow
horse
Returning to the spreadsheet example; the problem is that the behavior just described
means this code won’t work:
Dim myWorksheet As IWorksheet(Of Double)
For row As Integer = 0 To 10
myWorksheet。AssignCellCalculation(row; 1; _
Function(worksheet; cellRow; cellCol) _
myWorksheet。GetCellState(row; 0) _
myWorksheet。Calculate(10; 0))
Next
whereas this code would work:
Dim myWorksheet As IWorksheet(Of Double)
For row As Integer = 0 To 10
Dim temp = row
myWorksheet。AssignCellCalculation(row; 1; _
Function(worksheet; cellRow; cellCol) _
myWorksheet。GetCellState(temp; 0) _
myWorksheet。Calculate(10; 0))
Next
The difference between the two pieces of code is that the second one has the lambda
expression that uses the variable declared temp in the context of a loop。 For each iteration of the
loop; a new instance of temp is allocated; and hence each lambda expression has its own instance
of the row。
Assigning State Without Knowing the Type
When using generics types; one of the most mon problems occurs when you need to
work with proper types。 In the implementation of the IWorksheet interface; it is necessary to
implement the AssignCellState() method defined in the interface IWorksheetSerialize。
The explanation of IWorksheetSerialize is slightly plicated and relates to the problem
of loading an IWorksheet without knowing the type。 Say that you are saving an IWorkbook with
multiple IWorksheet instances。 Each IWorksheet instance is a specific type。 When you want to
load an IWorkbook; how does the loader know which types there are? The answer is that the
loader does not; and thus must first load a general type; and then make a specific cast。 Take a
look at the serialization source code in the project Devspace。Trader。mon and the namespace
Devspace。Trader。mon。ServerSpreadsheet。SerializerImpls; available as part of the down
loadable code。
…………………………………………………………Page 327……………………………………………………………