按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
Split() statement; and then individually investigating the resulting buffers。 If you had to do
that for 900;000 records; you would bee bored very quickly; and let’s not even talk about
how much time you would waste。
The Debug flag serves two purposes。 The first is to generate output to allow you to do a post
mortem analysis when trying to figure out a bug。 The second is to generate output when a bug
occurs in a production context。 By giving the user the ability to define a Debug flag; you are no
longer reliant on having the user explain to you step by step how to reproduce the bug。 All you
need to do is tell the user to activate the Debug flag (your program would probably have a menu
item for this); run the program until the bug occurs; and then send you the debug log file output
for analysis。
…………………………………………………………Page 316……………………………………………………………
294 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
Defining the IWorksheetBase and IWorksheet Interfaces
The worksheet is implemented using worksheet and workbook interfaces。 Remember that one
of the requirements is to have a spreadsheet implementation that is very fast。 This would mean
if a spreadsheet contained numbers; the best implementation would be a spreadsheet of
Double types。 However; if the spreadsheet contained string buffers; the best implementation
would be a spreadsheet of String types。 Figure 11…2 shows a spreadsheet of Double and
String types。
Figure 11…2。 Spreadsheet of strings and doubles
In Figure 11…2; the workbook references a worksheet of type Worksheet(Of Double) and
Worksheet(Of String); and in the general case; Worksheet(Of BaseType)。 You can see how an
interface using generics for a worksheet could be potentially defined: define a general
worksheet and define the actual type using generics。 The problem with this solution is
that a workbook would define a collection of mixed types。
You might be tempted to believe that Worksheet(Of Double) and Worksheet(Of String) are
of the type Worksheet(Of BaseType); and thus are all a single type。 This is not the case; because
with generics; a type that hasn’t been concretized is not a type at all。 Think of it as being
an almost type; and to make the program work; you need to concretize everything。 Figure 11…2
shows two concrete types: Worksheet(Of Double) and Worksheet(Of String)。 These are two
different types。 The two different types make it plicated for the workbook; because the
workbook wants to maintain a single collection of worksheets。 If we assume for the moment
that the worksheet interface is defined as follows:
Interface IWorksheet(Of BaseType)
End Interface
the workbook could reference the worksheet as this collection:
Dim _worksheets As List(Of IWorksheet(Of BaseType))
However; that reference is inplete; and the piler would want to know what BaseType
references。 To keep your options open; one solution is to not plete the BaseType; but let the
user of workbook figure things out; thus defining workbook as follows:
Class Workbook(Of BaseType)
Dim _worksheets As List(Of IWorksheet(Of BaseType))
End Class
…………………………………………………………Page 317……………………………………………………………
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 295
This solution seems to be a good one; but; in fact; it’s passing the buck。 The solution does
not address the problem of Figure 11…2 and forces the end user to solve it。 The core problem is
that Figure 11…2 uses generics to define worksheets of specific types; which means mixed
types that need to be addressed by the workbook。 In other words; a workbook can contain only
spreadsheets of a certain type; as in this example:
Workbook(Of String) workbook1
Workbook(Of Double) workbook2
It would seem that generics make everything more plicated。 However; there’s
more to this than first appears。
generics have not made things more plicated; but rather have required us to be
more explicit about what we actually want to do。 We want to be able to define specific work
sheet types; which means we have a mixed list of types that the workbook must manage。 As
explained in Chapter 9; non… generics list types cannot control whether or not a list contains
mixed types。
To solve the worksheet problem; we need to put on our object…oriented thinking caps。
First; what is a worksheet? It’s a spreadsheet that fulfills the role of a two…dimensional thing;
and it applies to all worksheets regardless of types。 Therefore; the first interface to define is a
base worksheet; as follows (do this in the ServerSideSpreadsheet project; as well as adding a
reference to the Devspace。Trader。mon project):
Imports Devspace。Trader。mon
Public Interface IWorksheetBase
Inherits IDebug
Sub Dimension(ByVal rows As Integer; ByVal cols As Integer)
ReadOnly Property MaxCols() As Integer
ReadOnly Property MaxRows() As Integer
End Interface
The interface definition of IWorksheetBase has one method and two properties。 The method
Dimension() is used to assign the maximum rows and columns of the individual spreadsheet。
The properties MaxRows and MaxCols return the maximum rows and columns。 The properties
and method have nothing to do with the specific type managed by the worksheet; but the inter
face manages to uniquely identify the instance as being a type of spreadsheet。
In the workbook code; the list of worksheets would be defined as follows:
Private _worksheets As IDictionary(Of String; IWorksheetBase) = _
New Dictionary(Of String; IWorksheetBase)
Now the workbook knows it has a series of worksheets; but the workbook does not know
or care about the types of the worksheets。 When users of the workbook want to manipulate an
individual worksheet; they can retrieve the worksheet from the workbook; but the users need
to know the worksheet’s type。
The spreadsheet is typically addressed using rows and columns; but to simplify declara
tions; there is also the ability to define something called the SheetCoordinate; which is a type
that has a row and column。 The SheetCoordinate is defined in ServerSideSpreadsheet as follows:
…………………………………………………………Page 318……………………………………………………………
296 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
Public Structure SheetCoordinate
Public Row As Integer
Public Column As Integer
Public Sub New(ByVal row As Integer; ByVal column As Integer)
If (row 《 0) Then
Throw New ArgumentOutOfRangeException(〃Row is below zero〃)
End If
If (column 《 0) Then
Throw New ArgumentOutOfRangeException(〃Column is below zero〃)
End If
Me。Row = row
Me。Column = column
End Sub
Public ReadOnly Property OneUp() As SheetCoordinate
Get
Return New SheetCoordinate((Me。Row 1); Me。Column)
End Get
End Property
Public ReadOnly Property OneDown() As SheetCoordinate
Get
Return New SheetCoordinate((Me。Row + 1); Me。Column)
End Get
End Property
Public ReadOn