C# 3.0 Design Patterns by Judith Bishop The unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification This page was updated June 20, 2008. UNCONFIRMED errors and comments from readers: [4] Aggregation; In the book it is written: "A has a B, and B can outlive A" I think correct is: "A has a B, and A can outlive B" [18-19]; The decorator pattern example does not work as presented. The confirmed errata for this error says that the List tags should be static -- wouldn't this solution mean that all tagged photo instances shared the same set of tags? [27] line 61 of the source listing; The variable subject is defined for a second time. This is a compiler error, no way will this code run. The subject variable could be reused by deleting the 'ProtectionProxy' type declaration just preceding it on the same line. {32} Method IsUnique(); Method is called IsUnique() but is later referenced as Unique(). I also wonder if the naming convention is not confusing, maybe UserExists() or something similar would be a more apropos name. {33} Check() method; If you are going to make a call to Authenticate() in the method it should be unconditional if password != null, otherwise the logic is not consistent. [54] line 38 of the source listing; Line 38 line uses s.equals(Name) where s is of type T. However there is no guarantee at this point that T implements IEquatable, this can generate a runtime exception. Fix: Add a generic constraint on T such that T implements IEquatable i.e. where T : IEquatable [55] the 60th line of code Example 3-1; IComponent holder = null; the 'holder' member should be _static_. {55} in the "Find (T s)" method; There appears to be a curly brace missing in the foreach block in the Find method. As the foreach block appears in the text: foreach (IComponent c in list) { found = c.Find(s); if (found!=null) break; } return found; } And that ends the method. The line "return found;" is at the same indent level as the rest of the interior of the foreach block, indicating that found would be return upon the first iteration through the loop. It appears that there is no closing curly brace for the method, either. However, this will compile and run, since a set of curly braces is not necessary when the block is composed of only one line, so the compiler sees this as a valid if statement: if (found!=null) break; and uses the next curly brace to close the foreach block, and then the final curly brace closes the method. The last three lines need to be unindented by one level each for clarity. (56) First paragraph after bullet points; The last sentence of this paragraph is "Example: Photo Library" in the normal text font and size. Previously, this was used as a heading marker, and was on its own line and much larger and bold. {60} Fifth Paragraph ; I think the line:- interface IComposite IComponant where T : IComponant is missing a : and should read interface IComposite : IComponant where T : IComponant (102) UML diagram; Class's name 'Class' should 'Client' {207} Last method public void Output; I was not familiar with the InvokeRequired property, so I looked it up on MSDN and I noticed something there that might be important to note or add to your book. Basically you should check IsHandleCreate when InvokeRequired is false, otherwise some possible bad things could occur. Thank you, Brian Holland FROM MSDN If the control's handle does not yet exist, InvokeRequired searches up the control's parent chain until it finds a control or form that does have a window handle. If no appropriate handle can be found, the InvokeRequired method returns false. This means that InvokeRequired can return false if Invoke is not required (the call occurs on the same thread), or if the control was created on a different thread but the control's handle has not yet been created. In the case where the control's handle has not yet been created, you should not simply call properties, methods, or events on the control. This might cause the control's handle to be created on the background thread, isolating the control on a thread without a message pump and making the application unstable. You can protect against this case by also checking the value of IsHandleCreated when InvokeRequired returns false on a background thread. If the control handle has not yet been created, you must wait until it has been created before calling Invoke or BeginInvoke. Typically, this happens only if a background thread is created in the constructor of the primary form for the application (as in Application.Run(new MainForm()), before the form has been shown or Application.Run has been called. (209) First sentence; I believe the first line should read as "In the Mediator's SignOn method, the Mediator's Send method was signed up to InputEvent. The book has Mediator constructor and should be Mediator's SignOn method. [235] Figure 10-5; Nonterminal class should aggregate abstract Term class not Terminal class