not possible。 But suppose that the type cannot be directly assigned。 Let’s say that value references a String that contains a number。 Then; using reflection; you can verify what ValueType and BaseType are and perform the conversion yourself: …………………………………………………………Page 329…………………………………………………………… 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 307 ElseIf TypeOf (value) Is String And _ GetType(Double)。IsAssignableFrom(GetType(BaseType)) Then The first part of the If statement asks if value is of type String。 The second part asks if Double can be assigned to BaseType。 If both are valid; it means the input is a String and the spread sheet type is a Double; so to convert; you only need to call Double。Parse()。 Providing this automatic conversion functionality for the caller of the code does not save code; but it centralizes it and makes it general。 The caller will not generally need to worry about the most mon conversions; as they will happen automatically (you will have implemented them)。 For those conversions that cannot be done; a cast exception is thrown; just as the orig inal object…based AssignCellState() would have thrown an exception。 The assignment is a series of casts and conversions that you need to do so that you can convert one type to another。 The main problem when converting types in this way is that the method…level generics parameter is a type that is not related to the type…level generics parameter。 Dim obj As Object = DirectCast(value; Object) Dim dValue As Double = Double。Parse(CStr(obj)) Dim objDValue As Object = CType(dValue; Object) CellState(row; col) = DirectCast(objDValue; BaseType) The first step is to convert the parameter into an object so that the cast operators that expect objects will work without the Visual Basic piler generating errors。 The If statement said that the input type is a String; and destination type is a Double。 Thus; the methods CStr() and Double。Parse() are called to convert the input string to a double number。 Once the string…to double functions have pleted; the CellState could be assigned; if it were not for the little problem of the generics…type level parameter。 The next steps of casting using CType() and DirectCast() are a boxing and unboxing of a value type。 This is necessary because the piler considers everything as an object; and thus you need to first convert to an object and then convert to the actual type。 ■Note The steps to convert from one generics type to another generics type would seem cumbersome; and to a degree they are。 Although the steps illustrated here are the minimum; they allow you to convert one type to another。 The steps are dangerous in that if you don’t know ahead of time whether the conversion is allowed; an exception could result。 In the example; an exception is almost impossible because the types were checked ahead of time; and an appropriate plan of action was taken。 Overall; the AssignCellState(Of )() method with generics parameters provides the ability to cleanly assign a value to the spreadsheet; and a clean and maintainable method to perform a conversion。 This goes back to the original requirement of being able to mix types safely。 Overriding the ToString() Functionality Debugging a data structure like a spreadsheet is a fairly plex task; because there is too much data。 The Worksheet(Of ) class implements the ToString() method and generates a string。 The string can be retrieved and then displayed using a method like Console。WriteLine()。 …………………………………………………………Page 330…………………………………………………………… 308 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 Here is the implementation of worksheet’s ToString() function。 Public Overrides Function ToString() As String Dim builder As New StringBuilder() Dim row As Integer For row = 0 To Cells。GetLength(0) 1 Dim needma As Boolean = False If _generateRowCounter Then needma = True builder。Append(row) End If Dim col As Integer For col = 0 To Cells。GetLength(1) 1 If needma Then builder。Append(〃;〃) Else needma = True End If If ellState(row; col) IsNot Nothing Then builder。Append(CellState(row; col)。ToString) End If Next col builder。Append(ChrW(10)) Next row Return builder。ToString End Function Because the worksheet can be large; StringBuilder is used to incrementally build a string that is returned。 ■Note The ToString() method is useful when you’re debugging or trying to perform analysis of the state of an object without actually debugging the program。 Thus; for improved debugging or runtime analysis; always implement ToString()。 Using the Spreadsheet With the interfaces and implementations plete; it is possible to use the spreadsheet。 The sample application is a spreadsheet that calculates the average of a set of numbers and then calculates how far each number is from the average。 Calculating an Average The spreadsheet calculates the average o