399 writer。Write(processor。Process(reader。ReadToEnd())) If TypeOf processor Is IExtendedProcessor Then writer。Write(DirectCast(processor; IExtendedProcessor)。Destroy()) End If End Sub End Module In the solution; the processor interface is tested to see if the interface is an instance of IExtendedProcessor。 If so; then the Initialize() and Destroy() methods can be called。 Extending interfaces and extending those classes that consume the old and new interfaces at the same time is keeping backward…patibility。 Backward…patibility is an important concept; because it implies you can gradually introduce new functionality into a working application without breaking old functionality。 Keeping backward…patibility without breaking working functionality is difficult; and there is a point where adding new functionality bees too plicated。 Once you reach this stage; you need to break backward…patibility by doing the following: Public Interface IExtendedProcessor Function Initialize() As String Function Destroy() As String Function Process(ByVal input As String) As String End Interface _ Public Interface IProcessor Function Process(ByVal input As String) As String End Interface The example will break backward…patibility due to the Obsolete attribute being associated with the IProcessor interface。 Thus; when any class or interface references the IProcessor interface; a pile error results。 The second parameter of Obsolete is true; which forces the piler error。 If you left out that parameter; when the interface is referenced; a piler warning; rather than a warning; is generated。 The IExtendedProcessor interface does not subclass IProcessor and includes the method Process()。 Thus; there are no dependencies between IExtendedProcessor and IProcessor; and all functionality in the application must use IExtendedProcessor rather than IProcessor。 ■Note Breaking backward…patibility is a major step; because your code cries that some code is broken and requires alteration。 However; sometimes you will need to break code; and when you do; make sure that the code cries “broken!” very loud。 Otherwise; you might get unexpected errors。 Now that we’ve updated the Bootstrap class and added the IExtendedProcessor interface; all of the samples in Chapter 10 will continue to function; and we can implement the frequency solution。 …………………………………………………………Page 422…………………………………………………………… 400 CH AP T E R 1 5 ■ L E A R N I N G A B OU T L I N Q Implementing a Frequency Solution The solution that we want to use is to read in the text; convert the text into binary objects; calculate some statistics; and finally write out the text。 The interesting part of this solution is that pieces of it have already been written。 If you remember in Chapter 10; there was a require ment to convert the lottery draws into binary form。 That code will be borrowed to implement the statistics functionality。 The statistics console application ( FrequencyProcessor) requires an IExtendedProcessor implementation。 The following is the plete implementation (note the imports from Chapter 10’s example)。 Imports LottoLibrary Imports ReaderWriter Imports System Imports System。Collections。Generic Imports System。IO Imports System。Linq Imports System。Text Friend Class LottoTicketProcessor Implements IExtendedProcessor Private _tickets As List(Of Ticket) = New List(Of Ticket)() Public Function Destroy() As String Implements IExtendedProcessor。Destroy Dim builder As New StringBuilder() Dim c1 As Integer For c1 = 1 To 46 1 builder。Append(〃Number (〃 & c1 & 〃) Found (〃) Dim foundCount As Integer = 0 builder。Append(((foundCount + FrequencyOfANumber(c1)) & 〃)〃 & ChrW(10))) Next c1 Return builder。ToString() End Function Private Function FrequencyOfANumber(ByVal numberToSearch As Integer) As Integer Dim query = From ticket In _tickets _ Where ticket。Numbers(0) = numberToSearch _ Or ticket。Numbers(1) = numberToSearch _ Or ticket。Numbers(2) = numberToSearch _ Or ticket。Numbers(3) = numberToSearch _ Or ticket。Numbers(4) = numberToSearch _ Or ticket。Numbers(5) = numberToSearch _ Select ticket。Numbers Return query。Count() End Function …………………………………………………………Page 423…………………………………………………………… CH AP T E R 1 5 ■ L E A R N I N G A B OU T L I N Q 401 Public Function Initialize() As String Implements IExtendedProcessor。Initialize Return 〃〃 End Function Public Function Process(ByVal input As String) As String _ Implements IProcessor。Process Dim reader As TextReader = New StringReader(input) Do While reader。Peek …1 Dim splitUpText As String() = reader。ReadLine。Split(New Char() {〃 〃c}) Dim dateSplit As String() = splitUpText(0)。Split(New Char() {〃。〃c}) Dim ticket As New Ticket( _ New DateTime( _