Vous êtes sur la page 1sur 82

UnofficialFluentC#Errata(andnotes)

TableofContents
UnofficialFluentC#Errata(andnotes)
TableofContents
Introduction
Chapter1
Page35,ambiguouslanguage
Page36,terminologyquestion(CLRcompliant)
Page38,terminology(CLIvsCLR)
Chapter2
Page51,samplecodecorrectnessquestion
Page54,diagramissue
Page56,awkwardwording(readercontribution)
Page62,ambiguouswording
Chapter3
Page88,codepresentationnitpick
Chapter4
Page98,terminology(syntaxerrors)
Page98,terminology(compilationerrors)
Page100,invalidcode(readercontribution)
Page104,disagreement:debuggingvsunittesting
Page109,disagreement:installationandwebapps...
Page112,incompleteinstructions(readercontribution)
Chapter5
Page123,terminology(nounsandverbs,sentencesandparagraphs)
Page124,minortechnicalerror(commentsbeingignoredbythe
compiler)
Page124,ambiguouslanguage(directives)
Page124and125,terminology(declarationsandstatements)
Page124,terminology(commands)
Page126,technicalerrorsaroundpunctuation
Page127,poornaming
Page128,technicalerror:statements
Page129,technicalerror:declarations
Page130,technicalerrors:const
Page131/132,omissions
Page133,clarification(identifiers)
Page134,terminology(parameterandargument)
Page134,namingconventions
Page136,confusion(atleast)aroundmemoryallocation
Page137,doesnewChar()createanobject?
1

Page137,constructorsuseidentifierstoo...
Page139,clarification(casting)
Page142,disagreement(commenting)
Page143,typo
Page145,clarification(readercontribution)
Page145,inconsistency(readercontribution)
Page148,terminology(attributes)
Page148,confusingdiagram
Page149,mostcommonlyuseddirectives
Page149,unnecessaryandconfusingbrackets
Page151,terminology(definingvsdeclaration)
Page151,terminology(constantvsconditionalcompilationsymbol)
Page151,technicalerror(preprocessorsymbolcasesensitivity)
Chapter6
Page156,terminology(expressionsasstatements)
Page157,terminology(lambdas)
Page158,terminology("equations")
Page158,terminology(objectsandtypes)
Page159,terminology(expressions)
Page159,terminology(statementsaren'texpressions)
Page160,codeformatting(spaces)
Page160,terminology(true)
Page161,terminology(remaindervsmodulus)
Page162,typo(readercontribution)
Page163,inconsistencyofsubtractionandaddition
Page163,disagreement(whentousebrackets)
Page163/164,confusion(precedence)
Page163/164,technicalerror(precedence)
Page165,typounopenedparenthesis(readercontribution)
Page166,terminology(conditionaloperatorsvsconditionallogical
operators)
Page166,technicalerror(compiletimevsexecutiontimeevaluation)
Page168,technicalerrorortypo(XORoperator)
Page168,codeformatting
Page168,alternativeanswerandwording
Page171,terminology(more"object"confusion)
Page172,terminology(yetmore"object"vagueness)
Page173,terminology(parametervsargument)
Page175,technicalerror(operators)
Page176,terminology(instanceofthemethod)
Page177,C#typealiases
Chapter7
Page181,terminology(commands)
Page188,codeformatting
Page188,nitpickaroundthenecessityofbracing
Page189,technicalerror(necessityforcaseclauses)
2

Page189,disagreement(whetherornottohaveadefault)
Page189,technicalerror(invalidcode)
Page190,codeerror(readercontribution)
Page190,codeerror(readercontribution)
Page190,formattingerror(wrongfont)
Page191/192,confusingrequirement
Page192,alternativeapproach(readersuggestion)
Page192,typoincode
Page194,terminology(forloops)
Page195,incorrectquotes(occurselsewheretoo)
Page196,confusingexample(readersuggestion)
Page197,disagreement(forvswhile)
Page198,codeerror(extrasemicolonvalidbutunintendedreader
contribution)
Page201,poorexample(goto)
Page204,meaninglessexample
Page205,invalidcodesample
Page207,terminology(variablesvsvaluesforarguments)
Page208,disagreement(behaviourforinappropriateargumenttypes)
Page209,codestyle(explicitcomparisonwithtrue)
Page210,technicalerror(try/catch/finally)
Page210,technicalerror(catchblock)
Page210,codestyle(throwex)
Page210,missingdescriptionofimportantfeature
Page210,inconsistency(catchvariablenamingreadercontribution)
Page211,disagreement(exceptionsandusers)
Page214,clarification(orderofcatchblocks)
Page214,invalidcode
Page219,insufficientinformation(readercontribution)
Chapter8
Page223,terminology(objectagain!)
Page225,incompleteness(delegates)
Page229,disagreement(theclassdesigner)
Page232,incorrectscreenshot
Page232,missingclass(readercontribution)
Page234,technicalerror(privateaccess)
Page234,disagreement(utilityofinternal)
Page238,disagreement(namingoffields)
Page240,clarification(readercontribution)
Page241,codeformatting(indentation)
Page242,technicalerror(incorrectdefaultaccessibility)
Page242,disagreement(reasonforusingexplicitaccessmodifiers)
Page242,incompletenessofmodifiers
Page246,poorsamplecode
Page249,terminology(immutable)

Page249,technicalerror(read/writeonlyautomaticallyimplemented
properties)
Page252,terminology(signature)
Page253,terminology(methods)
Page255,namingconsistency(readercontribution+Jon'sopinion)
Page256,terminology(instantiation)
Page256,technicalerror(accessibility)
Page257,codeerrors
Page258,disagreement(singlereturnstatement)
Page260,disagreement(howtoimplementanoverload)
Page260,terminology(defaultconstructors)
Page260,disagreement(alwaysprovidingaparameterlessconstructor)
Page262,technicalerror(incorrectcode)
Page262,poorcodeexample(naming)
Page264,technicalerror(memoryallocation)
Page264,technicalerror(publicvariables)
Page264,codestyle(parameternaming)
Page265,technicalerror(invalidcode)
Page267,confusingexplanation(garbagecollection)
Chapter9
Page271,terminology(structures)
Page273,incompletediagram(delegates)
Page273,incompletediagram(nestedtypes)
Page273,technicalerror(staticandinterfaces)
Pages274/275,technicalerror(valuestypesandthestack)
Page274,technicalerror(valuetypemagic)
Page277,terminology("objects"beingpassed)
Page280,invalidcode
Page281,disagreement(valuetypemembers)
Page284,badnaming(enum)
Page285,invalidcode(enumunderlyingtypes)
Page286,invalidcode(typeofvsGetType)
Page288,invalidcode(exerciseanswer)
Page291,invalidcode(interfacedeclaration)
Page291,invalidcode(interfaceimplementation)
Page293:disagreement(explicitinterfaceimplementation)
Page294,disagreement(frequencyofcasting)
Page295,terminology(implicitcasting)
Page296,incorrectexample(missingtype)
Page297,disagreement(isthencast)
Page299,technicalerror(boxing)
Page302,codeformatting
Page303,terminology("byvalue"and"byreference")
Page303,diagramconfusion
Page304,typo
Page305,terminology(passingbyreference)
4

Chapter10
Page313,incompletecoverageofnumerictypes
Page316,terminology(namespacesvsassemblies)
Page318,terminology(namespacesvsassemblies)
Page318,technicalerror(usingdirectivesandpreprocessordirectives)
Page319,technicalerror(namespacenames)
Page326,disagreement(CPUarchitectures)
Page326,badexamplecode(invalidoptimization)
Page327:partialdisagreement(floatingpoint)
Page327:disagreement(howmuchyouneedtounderstand)
Page327:technicalerror(incorrectcode)
Page328,terminology(decimal)
Page328,confusionandincompleteness(literals)
Page330,formattingerror
Page331,ambiguousexercise
Page332,technicalerror(Unicodecharacters)
Page333,technicalerror(Stringisaclass,notastruct)
Page333,technicalerror(supposedconversionfromchartostring)
Page333,typoincodeexample
Page333,terminology(escapesequence)
Page334,confusingexample(stringliterals)
Page334,inappropriateanalogy(WindowsExplorer)
Page334,unexplainedsubtlety(stringconcatenation)
Page337,terminology(immutable)
Page337,technicalerror(strings)
Page337,technicalerror(mutability)
Page339,disagreement(strengthof.NET'sdate/timeAPIs)
Page339,technicalerror(meaningofDateTimeOffset)
Page343,terminology(Juliandates)
Page345,disagreement(powerofTimeSpan)
Chapter11
Page357,terminology(awfuluseof"set")
Page359,technicalerror(arraymutability)
Page359,technicalerror(resizingarrays)
Page359,technicalerror(arrayequivalentofStringBuilder)
Page359,technicalerror(brokencode)
Page361,typo(brokencode)
Page363,typo(brokensyntaxdescription)
Page364,nastycode(ifconditionreturntrueelsereturnfalse)
Page367,technicalerror(arraysarereferencetypes)
Page367,oddexplanation(authordoesn'tknowaboutArray.IndexOf?)
Page370,technicalerrors(useofArrayListindexervsAddreader
contribution)
Page371/372/374,technicalerror(HashtablevsDictionary)
Page377,confusion(generics)
Page378,technicalerror(numbersoftypeparameters)
5

Page380,technicalerror(misunderstandingofHashSet<T>)
Page380,technicalerror(misunderstandingofSortedList<T>)
Chapter12
Page397,typo
Page400,technicalerror(codesample)
Page400,badpractice(inappropriatemutability)
Page401,confusionovercasting
Page402,missingbackreference
Page403,invalidcode(try/catchwithoutbraces)
Page403,invalidcode(missingclosingbrace)
Page404,invalidcode(missingclosingbrace)
Page406/407,invalidcode(missing"class"keyword)
Page406,invalidcode(methodmissingbracesentirely)
Page407,invalidcode(classshouldbeabstract)
Page407,invalidcode(methodsmissingreturntypes)
Page408,technicalerror(staticclassesandmethods)
Page408,terminology(inheritingvsoverriding)
Page408,terminologyandatypo("replacing"withnew,andoverridesvs
override)
Page409,technicalerror(singletonpattern)
Page409,badpractice(globalvariables)
Page409,incompleteness(extensionmethods)
Page411,disagreement(abstractclassmembers)
Page412,disagreement(usefulnessoftheclassdesigner)
Page412,invalidandbadcode(missingclasskeyword,badnaming
conventions)
Page415,terminology("semiabstractclass")
Page417,poorexample
Page419,badnaming
Page419,terminology(overridablevsinheritable)
Page421and422,technicalerror(extensionmethodsdon'thavetobe
public)
Page421,uncleardescription
Page421,terminology(usingdirective,notusingstatement)
Page422,technicalerror(invalidcode)
Page422,terminology(namespacesaren'treferenced)
Page422,terminology(extensionmethodscan't"override")
Chapter13
Page429,disagreement(codeduplicationimpact)
Page429,disagreement(commenting)
Page437/438,invalidcode(IntegerinsteadofInt32)
Page437/438,poornamingandpossiblyinvalidcode
Page437/438,poormodelling
Page437/438,codeformatting
Page443,terminology

Page443445,confusion(dependencyinversionandprogrammingto
interfaces)
Page448,codeformattingandparametertype
Page451,namingconventions
Page467,typo
Page477,technicalerrororlackofclarity
Page478,lackofclarity(conventionvsrequirementsforevents)
Page478,technicalerror(delegaterequirements)
Page478,incompleteness(eventdeclarationsyntax)
Page478,badcode(eventraisingmethod)
Page479,badcode(publiceventhandler)
Page479,technicalerror(delegateconstructor)
Page479,incompleteness(onlytheC#1.1delegatecreationexpression
isgiven)
Page491,disagreement(roleofSilverlight)
P491,typo
Chapter15
Page514,confusingcomment
Page514,VBism
Page521,typo(Ithink)
Chapter16
Page535,illegibletextduetobitmaprendering
Page545,arrowsaremisaligned
Page561,unexplainedreferencetonullablevaluetype
Page579/580,badpractice(suggestingtheuseofGetType()
Page586587,uglycode(useanobjectinitializer)
Chapter17
Page592,typo(threeratherthantwo)
Page592,confusingdescription
Page593,unnecessarilyverbosecode
Page597and598,typo(bulletnumbering)
Page615,incompletedescription(delegates)
Page615,invalidcode(typoofperiodforsemicolon)
Page617,typo
Page618620,opportunityformethodgroupconversions
Page619,layout
Chapter18
Page637,unnecessaryToString()calls(personalpreference)
Page641,typo(parametername)
Page642,disagreement(diagnostics)
Page644,technicalerror(Ibelieve)
Page645,typo(notinvalid,justodd)
Page652,terminology
Page661,incompleteness(exposingroutedcommands)
Chapter19
Page676,confusingcomment
7

Page683,codeformatting
Page683,codeclarity
Chapter20
Page715,typo
Page736,unfairC#vsXAMLcomparison
Page747,layoutissues(stretcheddiagram)
Page750,typo(WidthshouldbeHeight)
Page754,layoutissues(swappedscreenshots)
Chapter21
Page779,layoutissue(arrowtailoverlaystext)
Chapter22
Page802,typo(unmatchedparenthesis)
Page803,typo(caseofXmlDataProvider)
Page806,typo(unmatchedbrace)
Page813,confusionorbadpractice
Page813,badand/orinvalidcode
Page813,invalidcode
Page831,longwindedcode
Page831,codeformatting
Pages834and835,badcode(inappropriateuseof"as")

Introduction
ThisdocumentliststheerrorsthatI(JonSkeet)havefoundin
FluentC#byRebecca
Riordan
.Aswellasdefinitemistakes,Iveincludedformattingproblems,somesuggestions
aroundbestpracticesandotherareasofdisagreement.Ivetriedtomakeitclearwhichkind
ofitemiswhich.Someofthese(particularlyformattingsuggestions)aredefinitelyjust
nitpicksbutthey'rethingsInoticed,andthingsthatIknow
I
wouldappreciatebeingpointed
outtomeifsomeonefoundtheminsomethingI'dwritten.Smallthingslikeindentationcan
easilybefixedforfutureprintings,improvingtheoverallqualityofthebook.

Themoreimportantitemsaretheonesdescribedas"technicalerror"or"invalidcode"and
if,likeme,youcareabouttechnicaltermsbeingusedcorrectly,the"terminology"itemswill
beimportanttoyou.

Atthemoment,anyonecanreadandcommentonthisdocumentImayneedtorestrictitif
Ireceivealotofspamcomments,butifthathappensIllworkoutanotherapproachtoget
feedback.

Currentlythislisthasntbeenreviewedbytheauthororpublisher.GiventhatImjustas
fallibleasanyoneelse,pleasedontsimplybelievemeoveranyoneelseuseyourown
judgement.Asoneaid,however,IfrequentlyrefertotheC#LanguageSpecification,orthe
specforshort.WhereIgivesectionnumbers,theserefertotheC#4specification.

Finally,pleasedontregardthislistasdefinitivebyanymeans.ThesearejusttheitemsI
noticedwhilereadingthebookIhaventactedasatechnicalreviewerforthebook,or
anythingsimilar.Youllnoticethatthedensityofnotesismuchhigherforthechaptersonthe
C#language,whichisprobablypartlyduetomeknowingmoreaboutC#than(say)WPF
andeventhenotesI
have
gotontheWPFsectionsarelargelythingsliketyposandlayout
issues.Icantcommentontheaccuracyoftheothersections.Ifyouhavethebookyourself
andhavefoundanyerrors,pleasefeelfreetomailthemtome(skeet@pobox.com)andI'll
includethemhereaftercheckingthem.

AdditionasofJanuary2nd2012:I'vestartedreceivingadditionalerratafromotherreaders.
I'vemarkedeachonas"readercontribution"tomakethisclearineachcaseI'veatleast
checkedthatthecommentmakessenseandisasensiblesuggestiontoimprovethenext
editionofthebook.

Chapter1
Page35,ambiguouslanguage
Compiledlanguages...Theoutputisalwaysspecifictoasingleplatform
ItcouldbearguedthattheoutputoftheC#compiler(well,theMSC#compiler,atleast)
is
alwaysspecifictotheCLI,butbasicallythedistinctionbetweencompiledandinterpreted
ismorefuzzythanthepagemakesclear.Page36improvesthissomewhatwhenit
introducesaJIT,butitsstillnotmadeclearthatC#
is
acompiledlanguage.Alsonotethat
C#itselfdoesnt
require
aJITmodelMonoiscapableofbothaheadoftimecompilationto
nativecode(e.g.foriOS)andrunningtheILininterpretedmode.Thelanguage
specificationmakescertainrequirements,butit
doesnt
requireILastheoutputformat.
Page36,terminologyquestion(CLRcompliant)
C#isaCLRcompliantlanguage
ThetermCLRcompliantisnotoneImfamiliarwith.Itonlygets174hitsonMSDN,
comparedwith44,000+forCLScompliant.Itsnotclearwhetheritsmeanttobeanofficial
termornotIwouldpersonallyavoidusingitduetothisambiguity.(CLScomplianceisa
welldefinedterm,ontheotherhand.)
Page38,terminology(CLIvsCLR)
MicrosoftsversionoftheCLRrunsonvariousversionsofWindowsoperatingsystems[...].
TheCLRhasalsobeenportedtorun[...]
Thisseemstobeconflatingtwothings.TheCLRistheexecutionenginepartofMicrosofts
implementationoftheCLIspecification.ItsnotthattheCLRhasbeenportedtoother
platformsitsthattheCLIhasbeenimplementedonotherplatforms.

10

Chapter2
Page51,samplecodecorrectnessquestion
Thecodesampleonpage51whichismeanttoimplementcontrolresizinglooksexceedingly
suspecttome.Theauthorspecifiesthatitprobablywouldntworkforanyotherformbut
itsnotclearthatitwouldworkevenfor
this
form.Itscalesthetextboxesinproportiontothe
overallscalingoftheform,nottakingintoaccountthesizeofthelabelswhichalsohaveto
beaccommodated(withfixedwidthaccordingtothepictures).ImnotaVBprogrammerso
its
possible
thatthiswouldactuallyworksomehow,butitsnotatallcleartomehow.
Page54,diagramissue
Thediagramasthebottomleftofpage54hasWPFBrowserApplicationringed,witha
captionofThisiswhatwellcreatewhereasthetextnearbysays,JustchooseWPF
ApplicationfromtheWindowscategoryofVisualC#projects.
Page56,awkwardwording(readercontribution)
"Ifitisn'tvisible,choosePropertiesWindowfromtheViewmenu."
Thisshouldbeintheorderofexcecution:"...intheViewmenu,choosetheProperties
Window."
Orbetteryet,onaseparatelineindicatingthatitissomethingthestudentdoes:
"Viewmenu>PropertiesWindow".
(Therearesimilaroccurrencesthroughouttheremainderofthebook.)
Page62,ambiguouswording
Intellisenseisdescribedaskindoflikeautocomplete,butalotsmarter.Alotsmarterthan
which
autocomplete?Autocompleteisagenericterm,andIdsaythatIntellisensecounts
asoneimplementationofautocomplete.Itslikesaying,ADysoniskindoflikeavacuum
cleaner,butalotmorepowerful.

11

Chapter3
Page88,codepresentationnitpick
(Yes,thisonesreallyminor.)Thecodesampleshowsamethodcallwithoutany
whitespace:
MessageBox.Show("message","caption",MessageBoxButton.
Giventhatthisisaimedatbeginners,Iwouldreallyencourage"clean"codepresentation
whereatallpossibleanddensecodelikethisbecomesveryhardtoread.There'splentyof
roomhereforaspaceaftereachcomma.

12

Chapter4
Page98,terminology(syntaxerrors)
"Syntaxerrorsarethetyposoftheprogrammingworld"
withanexampleof
Messagebox("Hello")
(The"b"shouldbe"B"althoughusuallyI'dexpectthistorefertotheMessageBoxclass,
nota
method
calledMessageBox.)Idon'tviewthisasasyntaxerroratall.It'sperfectlyvalid
syntax
foraninvocation(ofeitheradelegateinstanceoramethod)butmemberlookupfails.
Iwouldreservetheterm"syntaxerror"forasequenceofvalidlexicaltokenswhich
can't
formavalidC#program.Forexample:
MessageBox("Hello"
Herethelackofaclosingparenthesisforthememberinvocationmakesthiscode
syntactically
invalid.
Page98,terminology(compilationerrors)
Thepreviouspointisfollowedby:
"Compilationerrorsarehalfwaybetweensyntaxerrorsandlogicalerrors."
Thissuggests
thatsyntaxerrorsaren'tinthemselvescompilationerrors,whichtheyare.Furthermore,if
we'vealreadyincludedmemberlookupfailureswithinsyntaxerrors,it'snotclearwhatthe
authorwouldcountasjusta"compilationerror".Noexampleisgiven,unfortunately.
Page100,invalidcode(readercontribution)
Thisvariabledeclaration:
Int32result
shouldhaveasemicolontocompletethestatement(astheprevioustwodo).
Page104,disagreement:debuggingvsunittesting
"Asaprogrammer,you'llspendalotofyourtimeinbreakmode(ifyou'relikemostofus,it
willfeellikeyouspendmoretimedebuggingthanwritingcode)"
Iwouldarguethatifyouspendalargeproportionofyourtimeinthedebugger,you'redoing
itwrong.Thiswouldhavebeenagreatpointtointroducetheideaofunittestingmaybe
pointingoutthatwhileexperimentationwasgoodinsomesituations,automatedtestingis
importanttogainconfidenceinthecorrectnessofyourcodeinthefaceofchanges
elsewhere.
Page109,disagreement:installationandwebapps...
"Yourapplicationmaybeabettermousetrap,butpeoplearen'tgoingtobeatapathtoyour
doorunlesstheycaninstallit."
Thismakesanassumptionthattheuserhastoinstallanapplicationinordertouseit.That's
simplynotalwaysthecase,andthisisoneexampleoftheclientapplicationbiasinthebook.
Whilewebapplicationsstillneedtobedeployed,theydon'tneedtobeinstalledbytheuser
andthingslikeWindowsPhone7applicationsdon'trequireseparatesetupprojects.

Page112,incompleteinstructions(readercontribution)
13

"IntheNewProjectdialog,selectSetupWizardfromtheOtherProjectTypes,Setupand
Deploymentcategory."
Under"SetupandDeploymenet"therearetwooptionsavailable:InstallShieldLEandVisual
StudioInstaller.Thetextshouldbemorespecificsomethinglikethis:
"IntheNewProjectdialog,selectOtherProjectTypes,SetupandDeploymentcategory,
VisualStudioInstaller,SetupWizard."

14

Chapter5
Page123,terminology(nounsandverbs,sentencesandparagraphs)
"JustlikespokenEnglish,C#hasnounsandverbs,sentencesandparagraphs."
Noitdoesn't.(I'darguethat
spoken
Englishdoesn'thaveparagraphseither,butthat's
anothermatter.)ThosetermsaremeaninglessasfarastheC#languageisconcerned,and
tryingtobendthe
real
termstobeabitlikenaturallanguageleadstomoreconfusionthan
clarity.Theanalogyisprettythinrightfromthestart,andIbelievethebookwouldbebetter
offwithoutit.
Page124,minortechnicalerror(commentsbeingignoredbythecompiler)
"Commentsareignoredbythecompiler,butarereallyimportantfortheprogrammer."
TheC#compilerdoesn'tignoreXMLcommentsifyouaskittogenerateanXMLfilefrom
yourcodewiththe"/doc:filename"flag.
Page124,ambiguouslanguage(directives)
(Labelfordirectives):
"Theseareinstructionstothecompilerandthe.NETframework"
It'shardtoseehowthesecanbeinstructionstotheframeworkitself,andsurelyallcodeis
aninstructiontothecompilerinsomerespect.Ican'tseehowareaderisgoingtogainany
insightfromthisstatement.
Page124and125,terminology(declarationsandstatements)
Boththediagramonpage124andthe"declaredelements"headingonpage125claimthat
declarationsarestatements.Someare(localvariabledeclarationstatements,forexample)
butmanyarenot(namespacedeclarations,typedeclarations,andtypemember
declarationsforexample).
Page124,terminology(commands)
Page124iswherewestartseeingtheterm"command"used.ThisisnotpartoftheC#
languagethere'snosuchthingasa"command"inC#.Thereareforstatements,while
statementsetcbutthesearesimplykindsofstatements,not"commands".Iftheauthor
wishestomakeupterminology,itwouldbeworthpointingouttothereaderthatshe'sdoing
so,sothatthereaderdoesn'texpectotherdeveloperswhoalreadyknowC#tousethe
sameterminology.
Page126,technicalerrorsaroundpunctuation
"C#doesn'thaveexclamationpoints[...],andquestionmarksmeanavariablecanbeempty.
We'lltalkaboutthatinchapter10."
Ihavethreeproblemswiththis:
Exclamationpointsareusedinlogicalnegationandinequalityexpressions
Questionmarksareusedfortheconditionaloperator,thenullcoalescingoperator,
andfornullablevaluetypesthelastofwhicharen'tthesameasmeaning"a
variablecanbeempty"
Ican'tfindanythinginchapter10whichtalksaboutnullabletypesanyway(there'sno
indexentryfornullorNullable)
15

Page127,poornaming
Thename
myClass
violatesnamingconventions
and
isgenerallypoorintermsof
description.Itshouldbe
MyClass
inordertofollow
Microsoftnamingconventions
,andclass
namesshoulddescribetheirpurpose
myClass
doesn'tgiveanyindicationastowhatit's
for.Inabookit'sreasonablynaturaltoneedtogiveexampleswhichdon'tserveanyreally
usefulpurposethey'rejustpedagogicalbutitwouldbeworthexplicitlystatingthis,and
possiblyusingmoreobviouslyexampledrivennames.Myfearisthathavingreadthisbook,
developerswillbehappytostickwiththenamessuggestedbyVisualStudiowhencreating
WindowsFormsapplicationsforexamplewholeapplicationswithForm1,Form2,Form3etc
insteadofmeaningfulnames.

Forabeginners'bookinparticular,asmallsectionemphasizingtheimportanceofnaming
wouldbeuseful.
Page128,technicalerror:statements
Manylinesonpage128arelabeledasstatementswhenthey'renot:
using
directives
Anamespacedeclaration
Aclassdeclaration
Afielddeclaration
Page129,technicalerror:declarations
"TherearetwotypesofdeclaredelementsinC#:variables[...]andconstants"
Thereare
lots
ofdifferentdeclarationswithinC#.Thosetwoarethetwokindsofdeclaration
statements
,buttheotherkinds(namespaces,classes,methodsetc)arestilldeclarations.
SeetheC#4specsections9.2,10.1,10.410.13,11.1,13.1,14.1,and15.1.
Page130,technicalerrors:const
Thebookcontainsthislineofcode:
privateconstElephantdumbo=newElephant()
Thisissupposedlyastatement.Problems:
It'snotastatementit'sa(nonlocal)constantdeclarationseesection10.4
newElephant()
isnotaconstantexpression,sothiswon'tevencompile.Itwould
ifitwere
readonly
insteadof
const
,butthat'sverydifferent.(Idon'tremember
seeingthereadonlymodifiercoveredinthebook.)
Page131/132,omissions
Thebookaskswhat'swrongwiththisdeclaration:
ConstcharmyChar="B"
Itcorrectlystatesthat"Const"shouldbe"const",butomitstheproblemthatthere'sno
conversionfromthestringliteral"B"tochar.Thisiscoveredabove,butitshouldhavebeen
includedhereas"somethingwhichwaswrongwiththedeclaration."Additionally,although
it's
not
anerror,thereaderhasn'tseenthattheC#alias"char"for"Char"sotheymaywell
haveguessedatthatbeinganerror.
Page133,clarification(identifiers)
16

"Anidentifiercancontainletters,numeralsorpunctuationafterthefirstcharacter."
Well,itcancontain
some
punctuation.Notjust
any
punctuationthough."a.b"isn'tavalid
identifier.
Page134,terminology(parameterandargument)
"Microsoftrecommendscamelcasingforprivateidentifiers[...]andthevaluesyoupassto
methods.(Thesearecalledparameters[...].)"
No,thevaluesyoupasstomethodsarethe
arguments
.Theparametersarethevariables
which
receive
theargumentvaluesastheirinitialvalues.ThisismentionedonP173,butit
wouldhavebeennicetobeaccurateinthedescriptionhere.
Page134,namingconventions
"Pascalcaseistherecommendeddefaultconvention.Useitforeverythingexceptprivate
identifiersandparameters."
Arguablythisone'samatteroftaste,butI'veseen
very
littlecodewherePascalCaseisthe
"default."Iguessitdependsonwhatyoumeanbya"privateidentifier"ifthatincludeslocal
variables,that'sfine...butinthatcase,thebookviolatestheconventionallovertheplace,
usingPascalCaseforlocalvariables.ThislookscompletelynonidiomatictomyeyesI'm
usedtoprettymuch
all
experiencedC#developersusingcamelCaseforlocalvariables.This
isabigdistractionthroughoutthewholebook.

(Forreference,the
DesignGuidelinesforDevelopingClassLibraries
bookcontainsthemost
commonlyreference
namingconventions
.Despitethenameofthebook,theseconventions
arereallyappropriatefor
all
developersconsistentnamingisn'tjustabenefitforclass
librarydevelopers.)
Page136,confusion(atleast)aroundmemoryallocation
Thiscodeispresented:
ElephantDumbo
Dumbo=newElephant()
Thelabelsclaimthat
"Nomemoryhasbeenallocated"
afterthefirststatement.Thisis
confusing.Thevariablerepresentsastoragelocationithasmemoryallocatedforit
somewhere
.There'sthenthisstatementforthesecondline:
"ThenewElephantiscreatedhere.Twothingshappenatthispoint:memoryisallocated,
andtheobjectisgivenaninitialvalue."
It'snotclearwhether"theobject"herereferstothe
real
objectwhichhasjustbeencreated
(assumingElephantisaclass,whichhasn'tbeenmadeclear)orthevariable.I
suspect
the
authorisjustusingtheword"object"incorrectlytomeanthevariable,butifIcan't
understandwhatshe'ssayingdespiteknowingC#well,Ican'tseehowareaderisgoingto
beanythewiser.
Page137,doesnewChar()createanobject?
Thisispotentiallyaterminologygap.Itypicallyusetheword
value
forareference,pointeror
valuetypevalue,and
object
tomeananinstanceofaclass(orboxedvaluetypevalue).The
codeonpage137I'mtalkingaboutlookslikethis:
CharLetter
17

Letter=newChar()
Letter='A'
Thisisdescribedas:
1. Declaretheidentifier
2. Createtheobject
3. Assignavalue
Myissueswiththisarearoundtheterminology:
Youdon'tdeclareanidentifieryoudeclareavariableby
specifying
anidentifierasits
name.
Thesecondlineassignsavalueaswellit'llbeeffectivelyU+0000inthiscase.
Page137,constructorsuseidentifierstoo...
(Referringto
newChar()
.)
"Noticethatithasparenthesesafterit.Thattellsthecompilerthatyou'recallingabitofcode,
notreferringtoanidentifier."
Wellyou
are
referringtoanidentifierbutthatidentifieris
identifying
thenameofthetype
whoseconstructoryouwanttocall.
Page139,clarification(casting)
"Youcangetaroundstrongtypingconstraintssimplybytellingthecompilerthatit'swhatyou
reallymeantodo."
Well,tosomeextent.Thecompilerwillpreventyoufromusingcastswhichcanclearly
never
work(e.g.acastfromastringexpressiontoint)andtheCLRwillmaintainrealtypesafetyat
executiontimehowevermuchyoucast,you'renot
really
goingtobeabletostoreavalueof
4.5inanintegervariable.
Page142,disagreement(commenting)
"Howdoyouknowwhattocomment?Thisiswhatexperiencehastaughttheprogramming
community:First,commenteverythingyouthinkyoumightnotrememberinsixmonths.
Thengobackandcommenteverythingyouthinkyouwill."
Absolutelynot.Writegoodcommentsdescribingwhatmethodsaremeantto
do
(particularly
forAPIsbetweencomponents),butthenonlywritecommentsinthe
implementation
when
it'snonobviousforexamplewhenyoucan'ttakeasimplerapproachduetoabuginan
externallibrary.Overlycommentedcodeis
less
clearthancodewhichhasmerelybeen
carefully
commented.
Page143,typo
Thecodeinthemiddleofpage143contains"Messagebox.Show"whichshouldbe
"MessageBox.Show".
Page145,clarification(readercontribution)
InsomeversionsofVisualStudio,youneedtomakesureallsettingsareshownbeforeyou'll
seethe"TaskList"settings.Todothis,openToolsMenu>Optionsandtickthe"Showall
settings"checkboxinthebottomleft.
Page145,inconsistency(readercontribution)
Step2oftheinstructionsonpage145talksaboutaddinga"ToDo"comment(andstep3
18

confirmsthatitshouldbe"Todo"(explicitlystatingthatcapitalizationisunimportant)butthe
example
onstep2is:
//Hack:Makeanoteofsomethingdodgy
Itshouldbe"TODO"(insomecapitalization)ratherthan"Hack".
Page148,terminology(attributes)
"They'relikedirectivesinmanyways"
Notreally.Therearea
few
usesthatthecompilerreallyknowsabout,butnotmany.They
certainlydon'tdeservetoliveasabranchundera"directives"boxinthediagram.
Page148,confusingdiagram
There'sa"directives"boxundera"directives"boxhowconfusing!What'sthisreally
supposedtomean?
Page149,mostcommonlyuseddirectives
"Thedirectivethat'susedmostoftenis
#if...#else...#endif
."
Isuspectthatthe
vast
majorityofC#developershavemore"using"directives(
using
System.Console
etc)thanpreprocessingdirectivesandquitepossiblymore
#region
directivesthanconditioncompilationdirectives,too.
Page149,unnecessaryandconfusingbrackets
Theexampleofconditionalcompilationlookslikethis:
#if(DEBUG)
Thismakesitlooklikeit'sreallyanexpressioninan"if"statement,andthatthebracketsare
necessary.They'renot,andI'verarelyseenthemused.
Page151,terminology(definingvsdeclaration)
Thenameofthetopicis"definingdirectives"thenameinthespecificationis"declaration
directives"seesection2.5.3
Page151,terminology(constantvsconditionalcompilationsymbol)
"[...]easywaytocontrolthedefinitionofthetwomostcommonconstantsusedwith
directives"
Theuseoftheword"constant"heresuggeststhatthesymbolhasa
value
whereasit's
reallyjustdefinedornot.TheC#speccallsthese
conditionalcompilationsymbols.
See
section2.5.1ofthespec.
Page151,technicalerror(preprocessorsymbolcasesensitivity)
"Directiveconstantsaren'tcasesensitive"
Yestheyare,likeeverythingelseinC#.HoldoverfromtheVBversionofthebook,
perhaps?

19

Chapter6
Page156,terminology(expressionsasstatements)
"Expressionsareakindofstatement"
Nothey'renot.Forexample,"x+1"isavalidexpression,butit'snotavalidstatement.
Page157,terminology(lambdas)
"Alambdaisananonymousexpression,roughlyequivalenttousingvartodeclarean
anonymousvariable."
Problems:
Alambdaexpressionreallyisn'tmuchlikeusingvar
Alambdaexpressionisakindofanonymous
function
,alongwithanonymous
methods.There'snosuchtermas"anonymousexpression"
varisn'tusedtodeclareananonymousvariableit'susedtogiveavariableatype
implicitly.Thevariablestillhasaname,soit'snotanonymous.
Page158,terminology("equations")
"WhatinspokenEnglishisgenerallycalledan"equation",inC#iscalledaliteral
expression."
Noit'snot."x+1"soundssomewhatlikeanequation,butit'snotaliteral.The"1"part
is
a
literal,butwouldn'tbecalledan"equation"bymostpeople.
Page158,terminology(objectsandtypes)
"technicallycalledtypes,ofwhichobjectsareonekind"
Anobjectisn'takindoftypeaclassis.I
suspect
that'swhat'smeanthere,butit'snotclear
atall.
Page159,terminology(expressions)
"LiketransitiveverbsinspokenEnglish,aC#expressionperformssomeactiononsome
thing."
Intheliteralexpression"5",whatactionisbeingtaken,andonwhat?Whataboutatype
expression,suchasFooin"
if(xisFoo)
"?Thesearebothexpressions,buttheydon't
representanykindofactionbeingtaken.
Page159,terminology(statementsaren'texpressions)
Thiscodeisdeemedtobeanexpression:
TextBox.Text="Hello,world"
Duetothesemicolon,it'sa
statement
,notanexpression.Withoutthesemicolonitwould
beanassignmentexpression.
Page160,codeformatting(spaces)
Theconditionaloperatorisshownwiththiscode:
x?y:z
I'veneverseentheconditionaloperatorusedwithoutaspacebeforethe?butwithspaces
aroundtheotherpunctuationitlookstoomuchlikeit'stryingtobeanullabletypetome.I'd
20

insertthespaceforconsistency.
Page160,terminology(true)
"truelookslikeavalue,andthetruthisitusuallybehaveslikeavalue,too.Butbecauseit's
actuallyanoperator,youcanredefinethemeaningoftrueandfalse"
Youcan'treallyredefinethemeaningoftrueandfalse.They'reonlyoperatorsinthecontext
ofoperatoroverloading,andthenI
believe
they'reonlyusedinthecontextofuserdefined
conditionallogicoperators(section7.12.2ofthespec).Idon'tthinkthisreallycountsas
"redefiningthemeaningoftrueandfalse".Bothtrueandfalse
are
validliteralexpressions
though(section2.4.4.1).
Page161,terminology(remaindervsmodulus)
Thisdescribesthe%operatorasthe"modulus"operator,whenit'smoreproperlycalledthe
"remainder"operator.(There'sanindexentryfor"modulo"inthespec,buttheworddoesn't
appearinthepageitreferstosection7.8.3.)ThedifferenceisonlyimportantinthatI'd
expectagenuinemodulusoperatorto
always
returnanonnegativevalue,whereasa
remaindercanbenegative.Differentlanguagesusethetermstomeanslightlydifferent
things,unfortunately,sothisisasomewhatpersonalopinionbutI'ddefinitelyuse
"remainder"tobeonthesafesideandtobeconsistentwiththespec.

EricLipperthasan
interestingblogpost
onthismattertoo.
Page162,typo(readercontribution)
Thefinalanswergivenonpage162is"x++"whichisfine,butthennotesaregiven:
"Anothertrick.Ifyousaidxx+1orx+=1youwereright[...]"
Thefirstoptionhereshouldbe"x=x+1"using"="insteadof"".
Page163,inconsistencyofsubtractionandaddition
Thiscodeisusedtotalkaboutprecedence:
2+3*4
Butthentheendoftheparagraphreads:
"becauseC#evaluatesexpressionsaccordingtoa
specifiedprecedence,andmultiplicationprecedessubtraction."
The"subtraction"here
shouldbe"addition".
Page163,disagreement(whentousebrackets)
"butbestpracticeistouseparenthesestodisambiguateanequation"
Well,onlywhenit'snotcleartostartwith.It'seasytogooverboardwiththis(justlike
commenting)andendupwithcodewhichishardertoread.Iwouldn'tusebracketsfor
just
a
simpleadditionandmultiplication,forexample.(Asnotedincomments,thisisdefinitelya
matterofopinionbutsimplyclaimingit's"bestpractice"isoverboardIMO.)
Page163/164,confusion(precedence)
Thedescriptionofprecedence(particularly"thepartoftheequationinsidetheparentheses
isalwaysexecutedfirst")isconfusing.It'simportanttodistinguishbetweenprecedence
(whichisaboutgrouping)andexecutionorder.EricLipperthastwogreatblogpostsabout
this:
PrecedencevsAssociativityvsOrder
21

Precedencsvsorder,redux

Page163/164,technicalerror(precedence)
Page163containsthiscodeasatest:
z=x++*y
Theexplanationonpage164states:
"The++operatorisplacedafterthevariablex,whichgivesitthelowestprecedenceofthis
set,soit'sevaluatedlast,givingxthevalueof2."
Thisisincorrect.Theexpression"x++"hastobeevaluated
before
themultiplication,asit's
anoperand.However,theevaluatedvalueoftheexpressionisthevalueofx
before
the
increment.Inparticular,iftheexpressionwere"x++*x++"(withx=1tostartwith)thenthe
resultwouldbe2,withxbeing3afterevaluationbecausetheleftoperandwouldbe
evaluatedfirst(givingaresultof1,x=2)thentherightoperandwouldbeevaluated(givinga
resultof2,x=3),thenthemultiplicationwouldbeperformed,givingaresultof2.
Page165,typounopenedparenthesis(readercontribution)
Thethirdsentenceofpage165hasaclosingparenthesis,butnoopeningparenthesis:
"Becarefulofthecapitalization)."
Itwouldn'tmakesensetoputtheopeningparenthesisearlierthanthestartofthissentence,
soI'dsuggestacorrectionto:
"(Becarefulofthecapitalization.)"
Page166,terminology(conditionaloperatorsvsconditionallogicaloperators)
Toremoveambiguity,Iwouldreferto||and&&as
conditionallogicaloperators,
whereas?:
issimplythe
conditionaloperator
.Thisoccursonpage169aswell.
Page166,technicalerror(compiletimevsexecutiontimeevaluation)
Whendiscussingthe||operator,there'sthisstatement:
"Sincexisindeedsmallerthany,(x<y)istrue,sothecompilerneverlooksattheincrement
operator."
No,the
compiler
looksatitasnormal(andwillcomplainifit'sinvalidetc).It'sjustnever
executed
.That'sabigdifference.
Page168,technicalerrorortypo(XORoperator)
Todetermineifexactlyoneofxoryistrue,thiscodeisproposed:
x>y
Ibelievetheintentionwastohaveacaretinstead,fortheXORoperator:
x^y
Page168,codeformatting
Thecode"x>y"hasnospaceafterthe">",fornoparticularlyobviousreason.
Page168,alternativeanswerandwording
Theanswerisgivenas:
"Areeitherxandytrue?"
x|y
Thequestionshouldbephrasedas"Areeitherx
or
ytrue?"andusingtheconditional
22

logical||operatorisavalid(andusuallypreferred)alternative.
Page171,terminology(more"object"confusion)
"You'veseenthatyoucreateanobjectusingadeclarationstatement"
No,adeclarationdoesn'talwayscreateanobject,andyoucancreateanobjectwithout
usingadeclaration(e.g.callingaconstructorinamethodargument).Itjustdeclares
something.Again,thisseemslikesimplysloppyuseoftheword"object".
Page171,terminology(yetmore"object"confusion)
"Aswe'llsee,youcandefineseveraldifferentkindsofobjects(calledTYPES)inC#,butthe
oneyou'llprobablyworkwithmostoftenistheOBJECT."
Ican'tseehowthiscanpossiblybereadinameaningfulfashion.Isuspectitshouldreally
bemorelikethis:
"Aswe'llsee,youcandeclareseveraldifferentkindsoftypesinC#,buttheoneyou'll
probablyworkwithmostoftenistheCLASS."
Page172,terminology(yetmore"object"vagueness)
"MessageBoxisanobject(inthiscaseaclass)"
No,MessageBoxisa
type
(inthiscaseaclass).Giventhattheword"object"appearsto
meananyoftype,class,variable,orobject,I'mgoingtostopreportingthisambiguitynowI
suspectitkeepscroppingupthroughoutthebookthough.
Page173,terminology(parametervsargument)
"Aparameterspecifiesavalue(eitheraliteralvalueoravariable)thatyoupasstothe
methodtoworkwith."
No,that'sanargument.Theparameteristhelocalvariablewhich
receives
theargumentas
itsinitialvalue(assumingit'sabyvalueparameter).Thisisactuallydiscussedatthebottom
in"Wordsforthewise"buttheauthorhasn'tusedthetermsconsistently.

Additionally,arguments
don't
havetobeliteralvaluesorvariables.Theycanbetheresults
ofpropertyaccesses,methodinvocations,lambdaexpressionsetc.
Page175,technicalerror(operators)
"Symbolicoperatorslike"+"and"/"areactuallysyntacticsugar.Thecompilertranslates
themintomethodcallslikeInt32.Add(Int32x,Int32y)"
NotforInt32itdoesn'tit(theMicrosoftimplementation,atleast)translatesthemintoIL
"add"instructions.UsingDateTimeasabetterexample,themethodcalledisthe
DateTime.op_Addition(DateTime,TimeSpan)member,whichisn'tthesameastheAdd
method.
Page176,terminology(instanceofthemethod)
"whileWindow.Show()iscalledonaninstanceofthemethod"
Isuspectthisshouldbe"aninstanceoftheWindowtype".
Page177,C#typealiases
Itwouldbeusefultoindicatethatthistableisincompleteitleavesoffuint,byte,sbyte,
decimal,float,double,long,ulong,short,ushort.Itwouldalsobeworthnotingthatthefull
.NETtypenameis"System.Boolean"etctheC#compilerdoesn'tresolveitasifyou'djust
23

typedBooleanitknowstheprecisetypeinvolved.Idon'tmindwhetherthetableis
completedorjustnotedtobeincompleteforthesakeofavoidingtoomuchconfusion,it
maywellmakesensetokeepittojustthetypesalreadypresent,solongasthere'san
appropriatenote.

Ifthecompletetablewererequired,itmightlookliketheonebelowI'veaddedanextra
commentjustformoreinformation.(Theextrainformationprobablywouldn'tbeappropriate
inthebook,butreadersmayfindituseful.)

C#alias

.NETframeworkname

Comments

sbyte

System.SByte

8bitsignedinteger.

byte

System.Byte

8bitunsignedinteger

short

System.Int16

16bitsignedinteger

ushort

System.UInt16

16bitunsignedinteger

int

System.Int32

32bitsignedinteger

uint

System.UInt32

32bitunsignedinteger

long

System.Int64

64bitsignedinteger

ulong

System.UInt64

64bitunsignedinteger

char

System.Char

Worksasa16bitunsignedinteger,but
shouldbetreatedasa"UTF16codeunit"
whichin
mostcases
canberegardedas
"Unicodecharacter",althoughrealityis
slightlymorecomplicated.

string

System.String

Sequenceofcharvaluesessentiallya
pieceoftext

float

System.Float

32bitbinaryfloatingpointnumber

double

System.Double

64bitbinaryfloatingpointnumber

decimal

System.Decimal

128bitdecimalfloatingpointnumber

object

System.Object

EverynonpointertypeinC#isconvertible
toobject.See
EricLippert'sblogpost
for
moreinformation.

Notethatthere'salso"void"whichisrelatedtotheSystem.Voidframeworktype,butthisis
notquitethesameasthealiaseslistedaboveyoucan'tuseSystem.VoidinC#code
whereasyoucanuseInt32inmostplaceswhereyoucanuseint,forexample.

24

25

Chapter7
Page181,terminology(commands)
"Inthischapter,we'llfinishupourexaminationoftheC#languagebyexaminingthe
intransitiveverbsofthelanguage:commands."
Again,theanalogyissomewhattorturedandtheterm"command"isnotastandardone.
Page188,codeformatting
Onthesamepagewhichstates:
"Thebracesaren'tabsolutelynecessaryherebecausethere'sonlyasinglestatementin
eachclause,butit'sneveramistaketousethem,andmanyprogrammers(includingme)
alwaysusethem."
Ithoroughlyapplaudthatsentimentbutfinditsurprisingthatontheverysamepage,the
bottomexample
doesn't
usebracesforthenestedifblock.Thisiscontinuedthroughoutthe
bookthebadpractice(IMO)ofusingifstatementswithoutbracesoccursallovertheplace.
Page188,nitpickaroundthenecessityofbracing
"Thesebracesarenecessary,becausetheelseclausecontainsmultiplestatementsina
block"
Therearetwothingswrongwiththis:
Thebracesaroundthefirststatementblockwouldn'tbenecessaryevenifthatwere
thecase
Thebraces
aren't
necessaryhereastheelseclauseonlycontainsasinglestatement
(anifelsestatement)
Evenwithoutthebraces,the"else"clauseswouldbehaveappropriately.Fromthespec,
section8.7.1,"Anelsepartisassociatedwiththelexicallynearestpreceding"if"thatis
allowedbythesyntax."Sothiswholeexample
could
bewrittenwithoutanybracesatall.
Page189,technicalerror(necessityforcaseclauses)
"Youmusthaveatleastonecaseclause,butyou'renotrequiredtohavemorethanone."
Incorrect.Aswitchstatementwith
just
adefaultlabelcompileswithnowarningsorerrors.A
switchstatementwithout
any
labelscompileswithawarning(CS1522)butnoerror.
Page189,disagreement(whetherornottohaveadefault)
"Thedefaultcaseisoptional,butavery,verygoodidea."
Thatentirelydependsonthecontext.Ifyou'redeliberatelyswitchingonsomethingwhich
maynotmatchanyofthegivencases,andyoudon'twanttotakeanyparticularactionin
thatsituation,whyisita"very,verygoodidea"tohaveanemptydefaultlabel?
Page189,technicalerror(invalidcode)
Thecodeinthebottomrightofthepageisinvalid(errorCS0163)becausecontrolreaches
theendofthedefaultlabel.Justlikecaselabels,thecompilerensuresthattheendofa
defaultlabelis
unreachable
.

Thecodeshouldbesomethinglike:
26

switch(x)
{
case1:
case3:
MessageBox.Show("1")
break
case2:
MessageBox.Show("2")
break
default:
MessageBox.Show("Somethingelse")
break//Thislineismissinginthebook
}
Notethatanyotherwayofavoidingtheendofthedefaultcasebeingreachablewouldwork
toothrowinganexception,orreturningfromthemethod.Usingabreakstatementisthe
mostcommonapproach,butit'susefultoknowthattheruleisaboutreachability,
not
about
"theremustbeabreakstatement".Seesection8.1oftheC#4specificationformore
informationaboutreachability.
Page190,codeerror(readercontribution)
Thelefthandexamplecodeonpage190endswith"break"justbeforetheclosingbrace.
Therearetwoproblemswiththis:
Itdoesn'thaveaclosingsemicolon,soit'snotavalidbreakstatement
It'snotinaswitchstatementoraloop(asfaraswecansee)soit'snotvalidtohave
abreakstatementhereanyway.
Basically,thebreakstatementshouldberemoved.
Page190,codeerror(readercontribution)
Theexamplesatthetopofpage190aremeanttoachievethesameresultbutthe
sideeffectsonthelefthandsideallmodifyx,whereasthesideeffectsontherighthand
sideallmodifyy.(It'snotamatteroftherighthandsideusingyuniversallyit'sstill
reacting
tothevalueofx.)
Page190,formattingerror(wrongfont)
Thecodeatthebottomofpage190isinaproportionalfont,ratherthanthemore
conventional(forprogramming)monospacedfontwhichisusedintheexamplesatthetopof
thepage.
Page191/192,confusingrequirement
Theexampleatthebottomofpage191/192isunfortunate:
"Ifxisequalto0,incrementx.Ifxisequalto5,decrementx.Ifxisequaltoy,setxto10."
Inthisspecificcase,itdoesn'tmatterifweviewthefirsttwoconditionsasbeingevaluated
"atthesametime"because0+1isnot5.However,supposeitwere:
"Ifxisequalto0,incrementxbyy.Ifxisequalto5,decrementx.Ifxisequaltoy,setxto
10."
Atthatpoint,whatshouldwedoifxis0andyis5?Shouldwecheckforxbeingequalto5
27

after
incrementingitbyy,leavingxas4overall?It'sthislogicalquestionofwhetherwe're
evaluating
onevalue
againstmultiplecases,orwhetherwe'recheckingaconditionandthen
potentiallychangingstatebeforethenextconditionisevaluatedwhichisthemostimportant
distinctionbetweenusing"if"vsusing"switch"herethefactthatthefinalconditioncan't
evenbeexpressedwithaswitchstatementisalmostincidental.

Thepreviousexample(inthesameexercise)wassimilarlyworded,butusedaswitch
statementtoachieveitleavingthisasabasicallyambiguousexercise,which
happens
not
tocauseproblemsbecauseofthevaluesinvolved.Exercisesshouldnotbeexpressedin
suchambiguoustermsinmyopinion.
Page192,alternativeapproach(readersuggestion)
Followingonfromtheconfusingrequirements,areaderhassuggestednotinganalternative
tothethreeindependent(andalwaysevaluated"if"statements).Wecanensurethatonly
one
statementbodyisexecutedusingif/else:

if(x==0)
{
x++
}
elseif(x==5)
{
x
}
elseif(x==y)
{
x=10
}
Asthispoint,whenreadingthecodeyoudon'tneedtoworrywhetherasideeffectwithin
onestatementbody(e.g.
x++
)willaffecttheevaluationofoneofthelaterconditions.
Page192,typoincode
ThetopquestiononPage191(repeatedonpage192)talksaboutsettingthevalueofabut
the
answer
onlyeversetsthevalueofx,nota.Toanswerthequestionasanswered,the
codeshouldbe:
switch(a)
{
case3:
a=5
break
case10:
a=15
break
case0:
break
default:
28

MessageBox.Show("something"
break
}
Thechangesaretothetwoassignments.

Alternatively,thequestioncouldbechangedto"Ifaisequalto3,setxto5.Ifaisequalto
10,setxto15.[...]"However,ifthat
sort
ofchangeismade,I'dsuggestusing"b"insteadof
"x",inordertokeepthefirstquestionentirelyseparatefromthesecond.
Page194,terminology(forloops)
"Therearethreecategoriesofiterationstatements:thosethatexecuteastatementblocka
specificnumberoftimes[...]"
That'sreallynotacategoryofiterationstatement.Itsohappensthatifyouusea"for"loopin
aparticularway,itwillexecuteanumberoftimes(barringbreak,continueandreturn)but
that'snotreallyhowitshouldbedescribed.
Page195,incorrectquotes(occurselsewheretoo)
Thesample"for"looponpage195usestwo"opendoublequote"characters.C#doesn'tuse
these"curlyquotes"itonlydealsusesthequoteswithintheASCIIcharacterset,whichare
typicallyshownas"straightquotes".

Thisoccursquitefrequentlyinthecode,butisparticularlynoticeableonpage195asthere
aretwoopeningquotesratherthanthemorereasonablelooking(butinvalid)open/close
quotepair.
Page196,confusingexample(readersuggestion)
Thethirdexampleofaforlooponpage196isasfollows:
for(Int32x=0x<5x++,MessageBox.Show(x.ToString()))

Thisisexplainedanddiscouragedatthebottomofthepage,butitcouldbeconfusingfor
readersgiventhatit'snotclearfromthesyntaxdiagramonpage195thatthisiseven
allowed.

Tobehonest,Ican'tremembereverseeingcodewhichtriedtodothisgiventhatthereare
anynumberofweirdthingsyou
can
doifyoureallytry,I'mnotsureitwasworthgivingthis
exampleatallortheexampleitselfshouldhavebeenputinaseparatebox.
Page197,disagreement(forvswhile)
"Butinaclassicforloop,theconditionsectiononlyevaluatesthecontrolvariable.Ifyour
conditionismorecomplicated,it'susuallyclearertouseoneofthetwoconditionaliterations
[sic]statementsthatarespecificdesignedforthatpurpose."
Iwouldn'tusethatasthewayofdecidingwhetherornottouseaforloopI'dusethe
questionofwhetherIwantsomethingtobeexecutedattheendofeachiteration(regardless
ofwhethertheiterationwasterminatedearlywithacontinuestatement)andwhetherornotI
wantedanextrainitializationstepwhichwascapableofdeclaringlocalvariablesforthe
givenscope.Iftheconditionitselfbecomestoocomplicatedfora"for"loop,Iwouldn'tuseit
29

verbatiminawhileordo/whileloopeitherI'dextractittoamethod.
Page198,codeerror(extrasemicolonvalidbutunintendedreadercontribution)
Thecodeonpage198toexplainthedifferencebetweendo/whileandwhilecontainsastray
semicolon:
Int32x=5
do
{
MessageBox.Show("Insidedo")
}while(x<5)

while(x<5)
{
MessageBox.Show("Insidewhile")
}

Thesecondwhileloopisn'twhatitappearstobe:thesemicolonbeforetheopeningbrace
makesitbehavelikethis:
while(x<5){/*donothing*/}

//Andthenthisisexecuted...
MessageBox.Show("Insidewhile")

Socontrarytothebook'sclaim,"Insidewhile"(which
isn't
insideawhileloop)willbe
displayedonce.Thecorrectfixisjusttoremovethesemicolon:
while(x<5)
{
MessageBox.Show("Insidewhile")
}
Nowitwon'tbeshownatall,asxisneverlessthan5.
Page201,poorexample(goto)
"Thecodesnippetbelowwouldbealoteasiertounderstandifitwerewrittenasaswitch
statement,butthere'snowaytoduplicatetheif(x==2|x==3)conditionasaconstant."
Wellassumingwe'rehappytoonlyevaluatexonce(theuseof|insteadof||hereisalready
dubious)youcanjustuseaswitchwithcaselabelsfor2and3:
switch(x)
{
case1:
x++
break
case2:
case3:
x
break
default:
30

x=y
break
}
Noneedforagotoandmuchnicer,IMO.Thepossibilityofhavingmorethanonecaseis
evenexplicitlycalledoutonpage189.Iftheauthor
really
wantstogiveanexampleforusing
goto,sheshouldcomeupwithabetterone.
Page204,meaninglessexample
Page204givessomesamplecode,andthensays:
"Tounderstandwhat'swrongwiththiscode,askyourselfsomequestions"
Wedon'tknowifthere's
anything
actuallywrongwiththecodewe'renevertoldwhatit's
meanttoachieve.
Page205,invalidcodesample
Therighthandsideofpage205containsthiscode:
if(a==z)|(a==q)
Thisisinvalidduetothepositioningoftheparentheses.It'salsonotclearwhy"|"isused
insteadof"||"hereIpersonallyuse|
very
rarely(Ialmostalwayswantshortcircuiting)and
that'sbeenthecaseeverywhereI'veworked,too.Whetherthetwoconditionsare
parenthesizedornotisamatteroftaste,as==hashigherprecedence("bindstighter")than
either|or||.Soanyofthesearevalid:
if((a==z)|(a==q))
if(a==z|a==q)
if((a==z)||(a==q))
if(a==z||a==q)

Whenusingthe"ConditionalOR"operator(thedoublepipe)Iprobablywouldn'tbotherwith
extrabracketingwhenusingthe"LogicalOR"(thesinglepipe)Iprobably
would
,tomakeit
clearIwasn'ttryingtoevaluate"z|a".SoIwouldprobablyusethefirstorlastofthese
optionsmostlikelythelast.
Page207,terminology(variablesvsvaluesforarguments)
Theexerciseonpage207askswhatshouldhappenif:
"Avariablepassedtoamethodcallcontainsthewrongtypeofdata"
Ithinkit'simportanttomakethepointthat(out/refparametersaside),theargumentisa
value
,nota
variable
.(It'salsoimportanttodistinguishbetweenthecompiletimetypeofthe
argumentexpressionandtheexecutiontimetypeofitsvalue.)
Page208,disagreement(behaviourforinappropriateargumenttypes)
Thestatedanswertotheexerciseaboveisthatanexceptionshouldbethrown.There'sa
labelsayingthat
sometimes
thewrongvaluecanslipinanyway.Well,the"wrongtype"here
can'tviolatethedeclaredparametertype,asotherwisethatwouldgiveacompiletimeerror.
Anexceptionisonlyappropriateifthevalueisinvalidforthecallandthewrongtypeisone
ofthe
least
likelyproblemshere,duetocompiletimetypesafety.
Page209,codestyle(explicitcomparisonwithtrue)
Thecodewithinpage209includes:
31

if(ThereIsAProblem==true)
Thissortofthingoccursfrequentlythroughthebook,andtomymindisn'tasclearassimply
usingthefactthatwe'vealreadygotaBooleanexpression:
if(ThereIsAProblem)
(I'veonlyhighlightedthisoccurrence.)
Page210,technicalerror(try/catch/finally)
Thesyntaxshownonpage210impliesthatatryblock
must
alwayshaveacatchblockit's
actuallyoptionalyouhavetohave
either
atleastonecatchblock
or
afinallyblock,orboth.
Page210,technicalerror(catchblock)
Thesyntaxshownonpage210impliesthatboththetypeandvariablenameinacatchblock
arerequiredthey'rebothoptional(althoughyouhavetospecifythetypeifyouwantto
specifyavariable,andyoudon'tincludetheparenthesesifyou'renotspecifyingeitherof
them).Soallofthesearevalid:
catch(IOExceptione){}
catch(IOException){}
catch{}

Thelastformisalmostneverusefulasof.NET2.0before.NET2.0(orin2.0+witha
suitableflag)it'spossibleforunmanagedcodetothrowanexceptionwhicha"catch
(Exception)"blockwouldn'tcatch.Thesedaysthatexceptioniscoercedintoa"normal"one
though.Youshouldalmostneverbecatchingsobroadlythough...
Page210,codestyle(throwex)
Thesamplecodeincludes:
catch(Exceptionex)
{
throwex
}
NotonlyisitabadideatocatchExceptioninmostcases,butthrowinglikethiswilldestroy
thestacktrace,makingithardertodiagnosetheoriginalproblem.Ifyou'renotgoingtodo
anythingotherthanrethrowthenthecatchblockshouldn'texistatall,butifyou
do
needto
rethrow,justusethethrowstatementlikethis:
catch(Exceptionex)
{
throw
}
Page210,missingdescriptionofimportantfeature
(Thisisthemostappropriateplaceforthisdescription.)
Thecodesampleshowsafinallyblockbeingusedtoclosesomething.Thisisfinebutnot
idiomatic,astypicallyyou'dusea"using"statementforthisinstead.Ican'tfindanything
describingthe"using"statementinthebook,whichisasignificantoversightinmyview.(If
yourreactionis"thebookcan'tincludeeverything"thenaskyourselfwhichismorelikelyto
beimportanttoafledglingprogrammer:handlingresourcescleanly,oraddingdropshadows
32

andblureffects,whicharebothcoveredinchapter19.)Page318
claims
thatitwillappear
laterinthebook,butIhaven'tseenanysignofit,andnoneof"usingstatement",
IDisposable,orDisposeappearsintheindex.

Notethatausingstatementdoesn'tallowyoutospecifyacatchblockbuttry/finallyblocks,
typicallyforresourcecleanup,shouldbe
much
morecommoninmostcodethantry/catchor
try/catch/finallyblocksandtheusingstatementistheidiomaticwayofrepresentinga
try/finallyblockwherethefinallyblockjustdisposesofaresource.PersonallyI'dratherusea
usingstatementwithanestedtry/catchblockthanexplicitlyuseatry/catch/finallyblock,
mostofthetime.

Sothecodeonpage210wouldusuallylookmorelikethis:
using(Streaminput=File.OpenRead("test.dat"))
{
//Usethestreamhere
}
It'snotclearwhat"x"wasmeanttobeintheoriginalexample,butinverymanycasesa
variablecanbedeclaredatthepointofresourceacquisitionandwhenyoudothatina
usingstatement,itmeansyou
can't
accidentallyusethevariableagainaftertheresource
hasbeenreleased,becauseit'soutofscope.
Page210,inconsistency(catchvariablenamingreadercontribution)
Onpage210,there'salabelforacatchblocksaying:
'Thenamespecifiedhereistheidentifieryou'lluseinsidethecatchblocktorefertothe
exception.Theconventionistocallit"e".'

However,inthecodesampleonthesamepage,wehave:
catch(Exceptionex)
{
throwex
}

PersonallyI'veseenboth"ex"and"e"usedalot,andIdon'thaveaparticularpreference
butitwouldbenicetoseeconsistencyhere.
Page211,disagreement(exceptionsandusers)
"TheMessagepropertyissetwhentheExceptioniscreated.Becauseitmaybedisplayedto
theuser,itshouldbeasinformativeaspossibleandincludesomesuggestionsaboutwhat
needstobedonetofixthings."
Idisagreewiththisapproach.Ifanexceptionisgoingtobeshowntoauser,itshouldbefor
thesakeofpassingittotechnicalsupport.Iftheexceptionisawareofsomethingthe
user
candotofixthesituation,thatshouldbehandledbytheapplicationappropriately
potentiallybyofferingtotakethecorrectiveactionontheirbehalf.
That
messageneedstobe
appropriateforusers,butexceptionmessagesshouldbeaimedat
developers.
Whaton
earthwouldanontechnicaluserbeabletodeducefrom(say)aNullReferenceException
andamysteriousstacktrace?It'seffectivelyincomprehensibleinformationwhichcanonly
33

beunderstoodbysupportstaff.

Noteonsomeambiguiitiesaroundthis:
Microsoft'sguidelines

do
talkaboutlocalizing
exceptionmessages,whichhasbeenabadideainmyexperience,andthey
do
talkabout
thepossibilityofusersseeingerrors.However,whenMicrosofttalksaboutincluding
informationwhichwouldhelpyoucorrecttheerror,Ibelievethey'retalkingaboutthe
developer
correctingtheerror,nottheuser.Inmyviewanexceptionshould
not
beshownto
usersbydefault.Theyshouldbesenttothedevelopers,withtheuserabletohavealookat
whatthereportcontainsiftheyreallywant.Itthereforemakessensetobe
careful
inyour
exceptionmessagesnottobevulgar,forexamplebutIwouldn'texpecttheuserto
actuallybeabletocorrectaproblembasedontheexceptionmessage.

Onthematteroflocalization:Ionceworkedonaprojectwhich
did
decidetolocalizeall
exceptionmessages,despitethefactthatallthedeveloperswereintheUK.Theresults
were:
Itwas
much
moreefforttoincludeusefulinformationinanexceptionmessage.It
involvedresourcefiles,translationsetc.Asaresult,you'doftenreuseanexisting
messageratherthancreatingaspecificoneforthesituation,soyou'dendup
conveyinglessinformation.
Anycodewhichthrewanexceptionwashardertounderstand,becausethemessage
wasn'tjustthereinthecodeinplaintext.
Whenstacktracescamebackfromothercountries,theywerehardertounderstand
we'dhavetotrytofindthelocalizedtext,thengetbacktotheoriginalresource
identifier,thentranslateitbackintoEnglish.Whatawasteoftime.
It
does
(potentially)makesensetolocalizeexceptionmessagesifyou'rebuildingaclass
librarywhichwilldefinitelybeusedbydevelopersinmultiplecultures,particularlyifyour
nativetongueisn'tEnglish.Manydeveloperswillbeusedtoreadingtechnicalmessagesin
Englishevenifit'snottheirnativetongue,andsometimesawellwrittenEnglishmessage
willbemoreusefulthanapoortranslationtoanotherlanguage...butit'sallajudgementcall
atthatpoint.You'dneedtobalancetheperceivedbenefitswiththesortofcostslistedabove.
Page214,clarification(orderofcatchblocks)
"Theorderofthecatchblocksisimportanthereyoushouldalwayslistthemfrommost
specifictomostgeneral,becauseonceanexceptionismatched,noneoftheotherblocksis
evaluated."
Thisfailstomentionthatunlesssomeoftheexceptiontypesaregenerictypeparameters,
thecompilerwillcatchthisproblemanywaysoit'snotsomethingyouhavetoconsciously
becarefulabout.
Page214,invalidcode
Notonlydoesthecodeonpage214havethesameproblemsnotedearlier(catching
Exception,havingacatchblockfornoreason
other
thantorethrow,andrethrowinginaway
whichdestroysthestacktrace)butit'salsoinvalid:
catch(Exceptionex)
{
throwe
34

}
Notethedifferentidentifiers(exande).
Page219,insufficientinformation(readercontribution)
"TheeasiestwaytosearchforSystemExceptionintheObjectBrower,andthenexpandthe
DerivedTypesnode."
Itmaybeworthnotingthatifyoucan'tseea"DerivedTypes"entrywhenyouexpandatype,
itmaybedisabled.Toreenableit:
ClicktheObjectBrowserSettingsiconintheribbon.
CheckDerivedTypes.
YoushouldthenbeabletoexpandSystem.SystemException,andexpanditslistofderived
types.

35

Chapter8
Page223,terminology(objectagain!)
"Thestatementbelowcontainsbothaclassandanobject.Whichdoyouthinkiswhich?"
publicStringMessage
There'snoobjectinthatstatementatall.There'sanaccessmodifier,thenameofaclass
(String),andthenameofapublicmutablefield(Message).Assuminganobjectofthe
containingclassiscreated,thepresenceofthisdeclarationwon'tcreateanynewobjectsin
itself.(Itwillstartwithadefaultvalueofanullreference,andmaythenbeassigneda
differentvaluewhichmaybetoa"new"string,oritmaybetoanexistingone.)
Page225,incompleteness(delegates)
Thediagramonpage225showsthekindsoftypeswhichcanbedeclaredinC#butomits
delegates.
Page229,disagreement(theclassdesigner)
It'snotatallcleartomewhysomuchtimeisgivenovertotheclassdesigner.Ifindit's
significantlylessefforttotype(say)amethoddeclarationintothesourcefilethantogointo
thedesignerandclickallovertheplacetogetwhatIwant.Whynotjustshowthecode?
Page232,incorrectscreenshot
Onpage231,we'reaskedtocreateanIngredientclassbutthescreenshotonpage232
showsjustaRecipeclass.ThescreenshotshouldbechangedtoshowjustanIngredient
class.
Page232,missingclass(readercontribution)
Onpage232,thetexttalksaboutaddingtheComponentclassbutnottheRecipeclass.
Giventhehighlystepbystepnatureoftherestofthissection,it'soddtoseetheRecipe
classonpages233and237.Thesimplestfixistochangepage232totalkaboutadding
boththeComponentandRecipeclasses.The"review"sectiononpage240talksabout
addingtheRecipeclass,butbythenwe'vealreadyseenitinseveralplaces.
Page234,technicalerror(privateaccess)
Privatemembersarestatedtobeaccessibleby"thetypethatdeclaresthem"they'realso
accessibletoany
nested
typeswithinthesamecontainingtype.(Thiscanbeveryhandy
sometimes.)
Page234,disagreement(utilityofinternal)
WhileIagreethatprotectedinternalisusedrelativelyrarely,Iwouldsuggestthatin
wellencapsulatedcode,manytypes
should
beinternal.Ifonlyyourassembly(andtest
assemblieswhichcanbegivenaccessviaInternalsVisibleToAttribute)isgoingtoneedto
accessaparticularUIwindow,forexample,whymakeitpublic?
Page238,disagreement(namingoffields)
(Thisisdefinitely
not
anerrorit'spurelyamatterofopinion.)
36


PersonallyI
don't
usean"m_"prefixforfieldnames.I'veworkedatcompanieswhichuse
prefixesI'veworkedatcompanieswhichdon't.PersonallyIdon'tlikethemmuchthey
interferewiththewayIsubvocalizecode.However,solongasyouonlyusethemfor
private
membersandsolongasyou'reconsistentwithyourselfandanyoneelseworkingonthe
codeit'sfineeitherway.

Ifindthatthecapitalizationmakesenoughdifferencetoalertmetowhethersomethingisa
variableoraproperty.Ofcourse,itmeansyouhavetofollowtheconventionsrigidly,but
that'snotreallyhard.
Page240,clarification(readercontribution)
"WhenyoutoldtheClassDesignerthatComponentinheritedfromIngredient,itchangedthe
diagram,butitalsomadeachangetothepropertiesshowninthePropertieswindowforthe
Componentclass."
Itmaybeworthnotingthatthisisthe"Properties"
window
(withtheclassname,access,etc),
notthePropertiespartofthe"ClassDetails"window(whichliststhemethods,properties,
eventsandsoon).
Page241,codeformatting(indentation)
ThedeclarationfortheQuantityOnHandpropertyhasn'tbeenproperlyindentedthe"p"of
publicisindentedonespacemorethantheopeningbrace.
Page242,technicalerror(incorrectdefaultaccessibility)
"Anyoftheaccessmodifierscanbeusedwiththeclassstatement[...].Ifyoudon'tspecify
themodifier,theclasswillbeprivate,whichishardlyeverwhatyouwant."
Thisisincorrect.Only
nested
classescanbeprivate,protected,orprotectedinternaland
thedefaultfortoplevelclassesisinternal.(Andagain,theclassdeclarationisn'ta
statement.)
Page242,disagreement(reasonforusingexplicitaccessmodifiers)
WhileInowagreethataccessmodifiersshouldbestatedexplicitly,myreasonsaredifferent.
Iviewthisasamatterofmakinganexplicitchoice:eachtimeIdeclareamember,Ishould
beputtingsomethoughtintohowaccessibleitshouldbe.Thedefaultsareactuallyvery
goodinC#(and
very
easytoremember:thedefaultisalwaysthemostprivateitcanbefor
thatdeclaration)butmakingitcleartosomeonereadingyourcodethatthisistheresultofa
deliberatechoiceisagoodthing.
Page242,incompletenessofmodifiers
Ifinditoddthat"partial"hasbeenincludedintheoptionsforaclassdeclaration,butnot
"sealed","abstract"etc.IsthisbecausethebookisheavilyclientUIfocused,andsomany
classesarepartialbecauseofthedesignerside?

TheC#specactually
does
list"partial"separatelytotheothermodifiers,butthatincludes
all
themodifiersinthe"classmodifiers"category,whereasthelabelonthediagraminthebook
suggeststhattheauthorisonlyconsideringaccessmodifiers(public,internaletc).
37

Page246,poorsamplecode
ThesamplecodefortheQuantityOnHandsetterthrowsjustExceptionwhen
ArgumentOutOfRangeExceptionwouldbemuchmoreappropriate.Thisisabooktargetedat
novicesitshouldn'tgivethembadhabitssuchasthrowingException(whichisalmost
never
appropriate).
Page249,terminology(immutable)
"Forthesakeofefficiency,somepropertiesofatypemaybeimmutable"
Apropertyisreadonlyratherthanimmutableperse.I'dalsoarguethatthereare
far
more
importantreasonsforcreatingimmutabletypesthanefficiencyclarityandthreadsafety
beingtheobvioustwo.
Page249,technicalerror(read/writeonlyautomaticallyimplementedproperties)
Inthecontextofreadonlyorwriteonlyproperties:
"Ineithercase,thesyntaxissimple.Yousimplyomitthegetorsetaccessorinafullproperty
declarationoromitanaccessorwithautoimplementedproperties."
Thisisincorrect.Youcan'tcreateafullyreadonlyorwriteonlyautomaticallyimplemented
property.Itwon'tcompile.Theclosestyoucancomeisanautomaticallyimplemented
propertywith(say)apublicgetterandaprivatesetter.
Page252,terminology(signature)
"Thereturntype,nameandparametersofamethoddefineits[...]signature"
(Thisisactuallyamultiplechoicequestion,butI'massumingtheauthorthinksthat
"signature"istherightoption"membership"wouldbeincorrect.)
Thereturntypeis
not
partofthesignatureofthemethod.Seesection10.6ofthe
specificationforconfirmation:"Thereturntypeisnotpartofamethod'ssignature,norare
thenamesofthetypeparametersortheformalparameters."
Page253,terminology(methods)
Thediagramonpage253showsconstructorsanddestructorsasmethods.They'renot
methods,althoughtheyaremembers.
Page255,namingconsistency(readercontribution+Jon'sopinion)
Thetextonpage255talksaboutanAllocatemethodwithtwoparameters:quantityand
schedule.ThescreenshotshowsasingleparametercalledQuantity(startingwithan
uppercaseQ).Presumablythe"schedule"parameterismissingasthescreenshotismeant
tohavebeentakenwhileintheprocessofaddingtheparameters,buttheexistingname
shouldbeconsistentwiththetextand.NETnamingconventions.

AccordingtoMicrosoft's
.NETnamingconventions
thisshouldbe"quantity"(asdescribedin
thetext).The
capitalizationrules
foridentifiersareeasytofollowintermsofwhethertouse
PascalCase(firstletterisuppercase)orcamelCase(firstletterislowercase):
Do use Pascal casing for all public member, type, and namespace names
consisting of multiple words.

Do use camel casing for parameter names.


Notethatthis
only
talksaboutpublicmembers:whatyoudowithprivatemembernamesis
38

uptoyou.PersonallyIstillusePascalCaseforallmethodsandtypenames,andcamelCase
forallnonconstantfields.(Iviewastaticreadonlyfieldofanimmutabletypeasbeing
philosophicallyequivalenttoaconstmember,eventhoughtherearesomesubtle
differences.)SoforthiscodeI'duse:

publicclassComponent:Ingredient
{
privateintquantityAllocated
publicintQuantityAllocated
{
get{returnquantityAllocated}
}

publicvoidAllocate(intquantity,boolschedule)
{
//Codehere
}
}
(I'dprobablyputtheQuantityAllocatedpropertyonasinglelineinthiscase,butthereisn't
roomonthepage.)
Page256,terminology(instantiation)
"Youcan'tcreatetypesormemberswithinamethod,butyoucaninstantiatetypesusinga
variabledeclaration."
Variabledeclarationsaremostlyorthogonaltoinstantiation.Youcaninstantiateatype
withoutusingavariableatall,andyoucandeclareavariablewithoutinstantiatingatype.
Forexample:

//Instantiation,novariable
Console.WriteLine(newStringBuilder())

//Variabledeclarationandinstantiation
StringBuilderfoo=newStringBuilder()
//Nonewobjectscreatedinthefinalline!
//Variabledeclarationandassignmentbutnoinstantiation.
StringBuilderbar=foo
Page256,technicalerror(accessibility)
"Thereareafewconstraintsontheaccessmodifierofaninstancemethod.First,itcannot
belessrestrictivethanthetypethatdefinesit."
Yesitcan.Forexample:
internalclassFoo
{
publicvoidBar()
{
}
39

}
Asidefromanythingelse,ifthegivenrulewerecorrectitwouldbeimpossibletooverride
ToString,GetHashCodeorEqualswithinaninternalclass...Thebookgoeson:
"Andsecond,forprettymuchthesamereason,itcannotbelessrestrictivethanthetypeof
anyofitsparameters."
Thisis
nearly
true,butnotquite.Forexample:
internalclassFoo
{
publicvoidBar(Bazbaz)
{
}
}
internalclassBaz{}
Hereit'sokayforthepublicBarmethodtohaveaparameterofinternaltypeBazbecause
thedeclaringtypeFooisinternaltoo.Thisisalltodowith
accessibilitydomains
seesection
3.5.2ofthespec.
Page257,codeerrors
Themethodshownonpage257hasanumberoferrors.Hereitisverbatim(slightlysmaller
thannormaljusttomakethelinesfit):
publicvoidAllocate(Int32quantity,Booleanschedule)
{
if(quantity<0)
thrownewArgumentException("quantitymustbegreaterthan0")
return
this.QuantityOnHand=m_quantityOnHand
m_quantityAllocated+=m_quantityOnHand
if(schedule==true)
thrownewNotImplementedException("NotYetBuilt")
}

Problems(inadditiontothecomparisonwithtrueandthelessthanidealexceptionchoice):
Theunconditionalreturnmidwaythroughthemethodmeanstherestofthecodeis
unreachable.
ThecheckshouldprobablycomparethequantityparameterwithQuantityOnHandas
wellas0ifwe'veonlygot5units,itdoesn'tmakesensetoallocate10,justlikeit
doesn'tmakesensetoallocate5units.Thismaybebestastwoseparatechecks,in
ordertogivesensibleexceptionmessagesineachcase.
Subtractingm_quantityOnHandfromQuantityOnHandwillleave0onhand.This
shouldprobablybethe"quantity"parameter(whichisn'totherwiseusedafterthefirst
check).
Dittotheincrementform_quantityAllocated(whichduetothelinebefore,will
currentlybeanoop,aswe'llhavesetm_quantityOnHandto0...)
Throwinganexceptionindicatingthatthemethodisn'tfullyimplemented
after
modifyingtheobjectisreallybadpractice.Thisfinalcheckshouldbethe
veryfirst
lineofthemethod.
Page258,disagreement(singlereturnstatement)
40

"Asageneralrule,everymethodshouldhaveasinglereturnstatement."
Idisagreewitheventhisloosestatement.Theauthor
does
acknowledgethatsimplicity
shouldtrumpdogma,butIwouldn'teventrytomakeasinglereturnstatementageneral
aim.Justwritethesimplestcodewhichachievesthedesiredresultthat'stheonlyaimyou
needhere.Sometimesthatwillbeasinglereturnstatementprettyoftenitwon'tbe.

Inparticular,ifyoufindyourselfwithalocalvariablewhichisonlyeverwrittentoonceper
executionpath,andthenusedasthereturnvaluewithoutexecutinganymoreusefulcodein
anyexecutionpath,youshould
strongly
considerremovingthevariableandreplacingeach
assignmentwithareturn.Ifyouknowyou'vedoneeverythingyouneedtoinamethod,why
notgivethatinformationtosomeonereadingthemethod?
Page260,disagreement(howtoimplementanoverload)
Abetterimplementationtotheonesuggested(IMO)wouldbe:
publicvoidAllocate(Int32quantity)
{
Allocate(quantity,false)
}
Whyreproducethesamelogic,whenyoucanjustdelegatefromoneoverloadtotheother?
Page260,terminology(defaultconstructors)
Thisisamatterofopinion,butIbelieveit'sclearertousetheterm"defaultconstructor"
only
foroneprovidedbythecompiler.Aparameterlessconstructoryouprovideyourselfisjusta
parameterlessconstructorwhygiveitadifferentname?
Page260,disagreement(alwaysprovidingaparameterlessconstructor)
Thebookdescribeshowaddingaparametertoaconstructorsignaturewillbreakallcalling
code,then:
"Thesolution?Alwaysdefinethedefaultconstructoryourself,evenifitdoesn'tdoanything."
Absolutelynot.Thereshouldonlybeaparameterlessconstructorifitmakessensetobe
abletoinstantiatetheclasswithoutprovidinganyotherinformation.Iftheclassischanging
inawaythat
requires
moreinformationtobeprovidedthanbefore,thenyes,that'sa
breakingchange.Eitheryouneedtorethinkthechange,ortakethehitofprovidingthat
informationfromallthecurrentcallers.Thealternativeistoneverhaveanyconfidencethat
yourtypeshaveaconsistentsetofinformation,becauseyoucan'tenforceitevenatcreation
time.
Page262,technicalerror(incorrectcode)
Thesyntaxforconstructorchainingisgivenincorrectlyonpage262.Here'sasnippetofthe
codeinthebook:
publicmyClass()
{
this.myClass(0)
}
That'snottherightsyntaxforconstructorchaining.Itshouldbe:
publicmyClass():this(0)
41

{
}
Thesameproblemcanbeseenatthetopofpage265.
(ThismaybeanothercaseofcodefromtheVBversionofthebookinvadingtheC#
version...)
Page262,poorcodeexample(naming)
Thesamplecodeonpage262usesaclassnameof"myClass".Thisisbothmeaningless
andviolates.NETnamingconventions.Additionally,thisexampleusestheC#alias"int"
insteadof"Int32"forparametersthat'sfineonitsown(andismypreferredstyle)butit's
inconsistentwiththecodeintherestofthebook.
Page264,technicalerror(memoryallocation)
"Whenyoucreateavariablewithadeclarationstatement,.NETallocatesenoughmemoryto
storethespecifiedtype'spropertiesandmaketheidentifieryou'vedeclaredavailablefor
use."
Noitdoesn't.Leavingasidewhenallocationactuallytakesplace,onlyenoughspaceis
allocatedforthevariabletohaveavalue.Forreferencetypes,thatvaluewilljustbea
referencesoonlyareferencesizedspaceisrequired.
Page264,technicalerror(publicvariables)
"Thepublickeywordcanonlybeappliedtotypesandmembers,notvariables."
Wellnot
local
variablesbutfieldsarevariablestoo,andthey'retypemembers,socanbe
declaredpublic.
Page264,codestyle(parameternaming)
TheMySentencemethodhasthisdeclaration:
publicstringMySentence(stringName)
Thisviolates.NETnamingconventionsduetotheparameternameaswellasbeing
inconsistentinitsuseofstringvsStringcomparedwiththerestofthebook.
Page265,technicalerror(invalidcode)
Asidefromthesyntaxerrorinthecodeatthetopofthepageforconstructorchaining,the
codeatthe
bottom
ofthepagecontainsaninvalidforstatement:
for(Int32yy<=5y++)
{
x++
}
ThiswillfailwitherrorCS0165:Useofunassignedlocalvariable'y'
Page267,confusingexplanation(garbagecollection)
Theexplanationofmemoryallocationandgarbagecollectiononpage267issufficiently
wrongheadedthatitbasicallyneedsacompleterewrite.Itignoresstackallocation,assumes
thatonlyasinglevariableeverreferstoanobject,claimsthat.NETapplicationshavea
defaultmemorylimitof2GB,andgenerallyIcan'tseeitmakinggarbagecollection
clearer
foranyone.

42

Chapter9
Page271,terminology(structures)
"Structures,whicharelikebabyclasses"
No,they'renot.Iknowthisisonlyapreamble,butthat'salazydescriptionwhichismore
likelytoharmthanhelp.(Thisiseffectivelyrepeatedonpage276,wherestructuresare
describedas"lightweightclasses".)
Page273,incompletediagram(delegates)
Thediagramonpage273mentionsclasses,structures,interfaces,andenumerationsbut
notdelegates.
Page273,incompletediagram(nestedtypes)
Thediagramonpage273showsthepossiblemembersofclassesandstructures,butomits
thepossibilityofhavingonetypeasthememberofanother.
Page273,technicalerror(staticandinterfaces)
Thediagramonpage273impliesthatinterfacememberscanbestatic.Theycan't.From
section13.2ofthespec:"...norcananinterfacecontainstaticmembersofanykind."
Pages274/275,technicalerror(valuestypesandthestack)
Thepictureonpage274andthelabelsonpage275propagatethemythof"referencetypes
liveontheheap,valuetypesliveonthestack."Thisisacommonmyth.It'san
oversimplisticdescriptionwhichendsupcausingconfusioninthelongterm.See
Eric
Lippert'sblogpost
formoredetails(therearevariousothersbyEricwhichare,ofcourse,
wellworthreading).
Page274,technicalerror(valuetypemagic)
"The.NETFrameworktypeSystem.ValueType,itselfareferencetype,containsthemagic
thatcausesitschildrentobestoreddirectlyonthestack."
Leavingthepreviouspointaboutthestacktooneside,the"magic"isn'tinthecodefor
System.ValueTypeit'sintheCLR.ValueType
does
containcodeforthingslikeEquals,but
notthecodetodeterminehowinstancesarestoredinmemory.

Page277,terminology("objects"beingpassed)
"Ontheotherhand,objectstendtogetpassedaround"
No,
values
arepassedaroundeithervaluetypevalues,orreferences.Actual
objects
are
neverpassedround.
Page280,invalidcode
Thiscodeisinvalid:
publicstructFirstStructure
{
publicFirstStructure(Int32x,Int32y)
43

{
this.X=x
this.Y=y
}

publicInt32X{getset}
publicInt32Y{getset}
}
Theproblemiswithusingautomaticallyimplementedpropertiesinstructuresthefields
mustallbedefinitelyassignedbeforeanypropertiesarecalled,sotheconstructorhastobe
changedto:
publicFirstStructure(Int32x,Int32y):this()
{
this.X=x
this.Y=y
}
However,that'snotthecodethatI'd
recommend
anyway.Mutablevaluetypeslikethisare
evil(andtheycertainly
shouldn't
bepresentedtobeginnerslikethis,withnowarning)this
structureshoulddeclaretworeadonlyprivatefields(xandy)anddeclaretworeadonly
propertieswhichreturntheirvalues.
Page281,disagreement(valuetypemembers)
"Sincethepropertiesofastructureshouldthemselvesbevaluetypes"
Notalways.Usually,butnotalwaysheck,it'sprettyraretocreateyourownvaluetypes
anyway,butwhenyoudoyou
might
haveareasontoincludeareferencetypefield.Idoso
inNodaTimesothat(say)aLocalDateTimehasareferencetotheappropriatecalendar.
Thisdoescreateproblemswiththedefaultvalueofthevaluetype(whichwillhavenullas
thevalueforthereferencetypefield)butthatcanbehandledinvariousways.
Page284,badnaming(enum)
Theexerciseonpage284suggestscreatinga"DaysOfTheWeek"enum.Itshouldbe
singular(DayOfWeekorDayOfTheWeek)by.NETnamingconventions.It'salsopretty
pointless,giventhatSystem.DayOfWeekalreadyexists.
Page285,invalidcode(enumunderlyingtypes)
Thesamplecodefordeclaringanenumis:
enumOrdinal:Int16{First,Second,Fifth=5}
ThiswillnotcompiletheC#aliases
must
beusedfortheunderlyingtypeinanenum
declaration.Thecorrectdeclarationis:
enumOrdinal:short{First,Second,Fifth=5}
NotethatI'veremovedtheredundantsemicolonattheendofthedeclarationtoo.
Page286,invalidcode(typeofvsGetType)
Thiscodesampleisinvalid:
StringConstantName=Enum.GetName(GetType(DayOfTheWeek),0)
TheauthortalksaboutGetTypeasanoperatorafewtimes,beforecorrectingherselfto
44

typeoflateron.IsuspectthismaybeacaseofmistakencutandpastefromtheVBversion
ofthebook.

Thecorrectedversionis:

StringConstantName=Enum.GetName(typeof(DayOfTheWeek),0)

NotethatalthoughEnum.GetName
can
beusedwiththenumericvalueassociatedwithan
enumvalue,it'smorecommonlyusedwithanactualenumvalue:

DayOfTheWeekday=DayOfTheWeek.Tuesday
Stringname=Enum.GetName(typeof(DayOfTheWeek),day)

Page288,invalidcode(exerciseanswer)
Thefollowingcode,givenasananswertoanexercise,isinvalid:
publicvoidShowDay(DayOfTheWeekday)
{
if(day>6)
thrownewArgumentException("Invaliddayargument.")
return

StringDayName=Enum.GetName(GetType(DayOfTheWeek),day)
MessageBox.Show(DayName)
Problems:
There'snoclosingbracetocompletethemethod
Theroguereturnstatement(indentedasshown,asifitwerepartofthe"if"body)will
maketherestofthemethodunreachable
There'snovalidationthatthevalueisn'tnegative(whichitcouldeasilybe)
6isamagicnumberhereitwouldbebettertouse
Enum.IsDefined(typeof(DayOfTheWeek),day)orusemyUnconstrainedMelody
librarywhichcandosimilarthingswithoutboxing
CallingGetNameisconsiderablymorecomplicatedthancallingToString

Page291,invalidcode(interfacedeclaration)
Theexampleofhowtodeclareaninterfaceisbrokenasittriestodeclareamethodas
explicitlypublic.ThisisprohibitedbytheC#specinsection13.2:"Itisacompiletimeerror
forinterfacememberdeclarationstoincludeanymodifiers."
Page291,invalidcode(interfaceimplementation)
TheexampleofhowtoimplementaninterfaceisbrokenasthepropertyMyPropertyis
(implicitly)private.
Page293:disagreement(explicitinterfaceimplementation)
"it'sneverwrongtochooseexplicit[interface]implementation"
45

Wellifyouwanttobeabletooverrideanimplementationinaderivedclassbutstillcallthe
originalimplementation,it'swrong...orifyouwanttobeabletocallthemethodusing
"dynamic".Basicallyexplicitinterfaceimplementationcomeswithabunchofrestrictionsand
odditiesit'samorecomplexchoicethantheonepresentedhere.
Page294,disagreement(frequencyofcasting)
"Anothertimeitcanhappeniswhenyouneedtopassanobjectofonetypetoamethodthat
declaresadifferenttypeasaparameter.That'scalledcasting,andyou'lldoalotofit."
Leavingasidethematterofwhether
objects
areeverpassed,I'dsaythatifyou'redoingalot
ofcasting,that'sadesignsmellyoushouldusually
see
whetheryoucanchangeyour
designtomakethecodetypesafewithoutcasting.
Page295,terminology(implicitcasting)
Thetermusedinthespecificationis"implicitconversion"ratherthan"implicitcasting".
Page296,incorrectexample(missingtype)
Theexampleofcastingonpage296usesatype(MyComponent)whichdoesn'texistinthe
classdiagramwhichismeanttoshowthetypesinvolved.
Page297,disagreement(isthencast)
"It'scommontousetheiskeywordinapatternliketheoneshowntestthencast."
Itshouldn'tbecommonbecauseusingtheasoperator(asshownbelow)isgenerally
preferred.I'dgenerallyonlyuse"isthencast"whenunboxing(whereyou
can't
useaseasily,
unlessyouunboxtothecorrespondingnullablevaluetype).
Page299,technicalerror(boxing)
Thefollowingcodeisshown(intwosnippets):
Int32x=5
x.ToString()
Thelabelthenclaims:
"ToString()isamethoddeclaredbySystem.Object,soxneedstobeboxed."
Exceptitdoesn't,actually.Therulesaroundcastingarequitecomplex,butinthiscasethe
compileremitanonvirtualcalltoInt32.ToString.Inothercasesitcanemitavirtualcallbut
using"constrained"intheIL.Whateverthedetails,there'snoboxinginthecasegivenhere.
Page302,codeformatting
Theindentationinthecodeonpage302hasvariousproblems.
Page303,terminology("byvalue"and"byreference")
"Whenyoupassavariableasanargumenttoamethod,themethodreceivesacopyofthe
valueonthestack.Inthecaseofreferencetypes,itreceivesacopyofthereferencetothe
valuesintheheap(inotherwords,referencebyreferenceandvaluebyvalue)."
Thefirstsentenceofthisisn'tunreasonable(thestackisanimplementationdetail,buthey)
butthesecondsentencetalkingabout"referencebyreference"isincorrect."Passby
reference"hasaveryspecificmeaningwhich
isn't
appropriatehere,anditbegsthequestion
ofwhathappenswhenyouuse"ref"withareferencetypeparameter.
46

Page303,diagramconfusion
Thediagramwhichismeanttoexplainthepreviousparagraphsisincomprehensibletome.
It'sreallynotclearwhatit'smeanttobeshowingIcan'teventellwhetherornotit's
accurate,becauseIcan'tunderstandit.
Page304,typo
Thebottombulletinthelistshouldread"passedbyreference"ratherthan"passedbyvalue"
otherwiseitdirectlycontradictsthethirdbullet.
Page305,terminology(passingbyreference)
"TheC#keywordforpassingavaluebyreferenceisref."
No,inthiscasetheauthorreally
does
meanvariable.Aspersection10.6.1.2ofthespec:
"Whenaformalparameterisareferenceparameter,thecorrespondingargumentina
methodinvocationmustconsistofthekeywordreffollowedbyavariablereference."Soyou
can't
justuseanyvalueyou
must
useavariable.Thevariable's
value
isnotpassedatall.

47

Chapter10
Page313,incompletecoverageofnumerictypes
TheelevennumerictypesmentionedinthechapterignoresSystem.Numerics.{BigInteger,
Complex}.Eveniftheyweren'tgoingtobecovered,theyshouldhavebeenmentioned.
Page316,terminology(namespacesvsassemblies)
"We'llneedtoaddareferencetotheSystem.Speechnamespace.Youaddreferencesfrom
theAddReferencedialog"
No,thataddsareferencetoanassembly.Assembliesandnamespacesaredifferentthings.
Forexample,tousemostofthetypesintheSystem.Linqnamespace,youneedtoadda
referencetotheSystem.Coreassembly.
Page318,terminology(namespacesvsassemblies)
"Youmustaddanamespacereferencetotheprojectbeforeyoucanreferenceitintheusing
directive."
Youhavetoaddan
assembly
referencebeforeusinganytypewithinthatassembly
(regardlessofusingdirectives),andaddingausingdirectiveforatypeornamespacewhich
isunknownviaanyoftheassemblyreferenceswillcauseacompiletimeerror.
Page318,technicalerror(usingdirectivesandpreprocessordirectives)
"Althoughitdoesn'tbeginwithahashsign,like#ifor#define,thisversionofusingreallyisa
preprocessordirective"
No,it'snotatleastnotinthespecterminology.It'sadirective,butit'snotapreprocessor
directive.Thoseareallcoveredby2.5ofthespec,whereasusingdirectivesareinsection
9.4.
Page319,technicalerror(namespacenames)
"Thenameofthenamespacemustbeavalididentifier."
No,ithastobea
qualifiedidentifier
inspecterms.Inparticular,identifierscan'tcontain
periods(soyoucan'tdeclareavariablecalledfoo.bar)whereasnamespacedeclarations
can:
namespaceFoo.Bar{}
(Oh,andnamespacedeclarationsaren'tstatements.)
Page326,disagreement(CPUarchitectures)
"Mostmoderncomputershave32bitprocessors"
Increasingly,desktopsandlaptopstypicallyhave64bitprocessors.Thatdoesn'tmeanit
wouldbeagoodideatostartusing"long"everywherethough.
Page326,badexamplecode(invalidoptimization)
Thecodeonpage326attemptstodemonstrateanoptimization.
Thecodebeforeoptimization:
for(Int32x=1x<=10000x++)
{
48

a=b/123
}
Thecodeafter"optimization":
c=1/123
for(Int32x=1x<=10000x++)
{
a=b*c
}
Eventhoughthisexampleishopelesslyincomplete(itdoesn'tshowthetypesofa,borc)it's
stillclearlyincorrectbecauseinthe"optimized"version,foranynoninfinitevaluesofb,a
willsimplybe0afterwards,ascis0.Thecodeperforms"1/123"as
integer
division,giving
aresultof0.

Moralofthestory:don'ttrytobeclever.Makeyourcodecorrectbeforeyoutrytooptimizeit
(andmakesureyouhavetestssothatyoucanvalidateit'sstillcorrectafterwards).Then
makesureyou'reoptimizingtheright
bit
ofcode.Thenuseappropriatemeasuringtoolsto
checkthatyouroptimizationsarereallyhelping.Thencheckthattheperformancebenefitis
worthanyreductioninreadabilityorelegance.
Page327:partialdisagreement(floatingpoint)
"Well,here'sthetrickythingaboutfloatingpoints:they'reonlyapproximationsofavalue."
Itreallydependsonwhat'smeanthere.Eachfloatingpointvalue
is
anexactvalue.
However,theremayhavebeenanapproximationinvolvedinconvertingitintoabinary
floatingpointvaluetostartwith.Forexample,theliteral"0.1d"isonlyapproximately0.1,but
it
is
anexactvalueinitself.
Page327:disagreement(howmuchyouneedtounderstand)
"Forgeneraluse,there'sreallyonlyonetechniqueyouneedtoremember"
Ithinkthat'sanoversimplification.I'mnotsayingyouneedtounderstand
everything
about
floatingpoint,butyou'relikelytocomeunstuckifyoubelievethat
all
youneedtoknowisnot
tocomparethemforequality.There'sthesituationsinwhichit'sappropriatetouseeach
type,forexample.

(AcoupleofarticlesI'vewrittenforthosewhowanttoknowmore:
binaryfloatingpoint
and
decimalfloatingpoint
in.NET.Thereare,ofcourse,hundredsofsimilarpostsaroundthe
web.)
Page327:technicalerror(incorrectcode)
Thiscodeissuggestedinsteadofanequalitytest:
if(MyFloat1MyFloat2<0.0000001)
Problemswiththis:
Itshouldbeusing
Math.Abs(MyFloat1MyFloat2)
otherwiseifMyFloat1=0
andMyFloat2=100000,that'sstillgoingtoevaluateto"true"...
Itfailstotakescaleintoaccount.Twotiny,tinyvaluesmayneedtobeveryclose
indeed(withadifferencefarsmallerthan0.0000001)tobeusefullyconsideredequal
20
whereastwovery
large
values(e.g.10
)couldsensiblybeconsidered"equal"even
49

iftheydifferbyathousandormore.
Page328,terminology(decimal)
"Likeafloatingpointnumber,the.NETFrameworkDecimaltypeisalsousedtostorereal
numbers."
Notjust
like
afloatingpointnumberdecimal
is
afloatingpointtype.It'sjustafloating
decimal
pointtypeinsteadofafloating
binary
pointtype.
Page328,confusionandincompleteness(literals)
"Likeanyvaluetype,decimalscanbeinitializedbyassigningthemavaluedirectly"
It'snotreallyclearwhat'smeantbythispossiblythatthereareliteralsfordecimal?Ifso,it
wouldbeusefultoshowanexample(e.g.0.1m)althoughtherecertainlyaren'tliteralsfor
all
valuetypes.ThesuggestiontocallthefiveparameterconstructorissomewhatbizarreI
thinkit's
highly
unlikelythatanentrylevelprogrammerisgoingtoneedthatanytimesoon.
Page330,formattingerror
There'sanoddlinebreakaboutathirdofthewaydownpage330,withalinecontainingjust
"and"onitsown.
Page331,ambiguousexercise
"DeterminewhetherChar1orChar2comesfirstinthealphabet"
Thisisambiguousdoes'X'comebefore'a'?Does'x'comebefore'A'?Whatabout
nonalphabeticornonASCIIcharacters?
Page332,technicalerror(Unicodecharacters)
"...youshouldbeawarethatasinglelogicalcharactermightmaptomorethanoneUnicode
character.Accentedcharacters,forexample,requiretwocharacters."
Notheydon't.LookattheUnicodecodechartfor
C1controlsandLatin1supplement
lots
ofaccentedcharactersthere,insinglecharacters.Nowyou
can
normalizethesetoseparate
theaccentfromthecharacterit'sappliedto,butyoucertainlydon'thaveto.

It'spossibletheauthorwasreallythinkingofcharactersoutsidetheBasicMultilingualPlane,
whichrequiretwoUTF16codeunitstorepresentasingleUnicodecodepointbutthat's
gettingsomewhatmoretechnical,andit'sunlikelythatthetargetreadershipisreally
interestedingoingthatdeep.

Page333,technicalerror(Stringisaclass,notastruct)
"Inthe.NETFramework,theyarerepresentedbytheSystem.Stringstructure.Likeany
valuetype,youcaninstantiateaStringdirectlyorbycallingoneofitsconstructors."
It'sstillnotclearwhatismeantby"instantiateaStringdirectly"butStringisdefinitely
not
a
valuetype.Fromsection4.2.4ofthespec:"Thestringtypeisasealedclasstypethat
inheritsdirectlyfromobject."

Page333,technicalerror(supposedconversionfromchartostring)
(WithanexampleofusingastringliteraltoassignavaluetoaStringvariable.)
50

"Makesuretousedoublequoteshere.SinglequotesdelimitaChar,notaString.Ifyouuse
them,thecodewillwork,butitwillcallanextra(unnecessary)conversionoperation."
No,itwillfailtocompile.TryingtousemultiplecharactersinacharliteralwillgiveCS1012
("Toomanycharactersincharacterliteral")andtryingtoassignavalidcharliteraltoastring
variablewillgiveCS0029("Cannotimplicitlyconverttype'char'to'string'").
Page333,typoincodeexample
Thecodeexamplegivencontains:
StringMyString="Johnsaid,\"MyDocument\Files.\""
Thereshouldbean"s"ontheendofDocument.Thesamemistakeisrepeatedinthe"fixed"
versionusingaverbatimstringliteral.
Page333,terminology(escapesequence)
"\r"isreferredtoas"return"inthebookit'smorecommonly"carriagereturn".(Additionally,I
wouldpersonallyuse"linefeed"for"\n"butherethespecagreeswiththebook,callingjust
"newline".)
Page334,confusingexample(stringliterals)
Here'sacodesampleatthetopofpage334:
StringString1="Hello"
StringString2="Hello"
BooleanTheSame=(String1==String2)
Thisdoesn'tachievewhatitlookslikeitdoes.Thesamecodewillproducethesameresultin
Java,eventhoughJavadoesn'thaveoperatoroverloading,sowouldbecomparing
references.Thiscodeiscomparingtwo
identical
referencesString1andString2refertothe
exactsameobject,nottwo
equal
objects.(That'sguaranteedbythespecsection2.4.4.5:
"Eachstringliteraldoesnotnecessarilyresultinanewstringinstance.Whentwoormore
stringliteralsthatareequivalentaccordingtothestringequalityoperator(7.10.7)appearin
thesameprogram,thesestringliteralsrefertothesamestringinstance.")

NowinC#,thetwostrings
are
actuallycomparedbysemanticvaluewhenthe==operatoris
used,duetooperatoroverloading(butonlywhentheoperands'compiletimetypesareboth
stringanothersubtlety).However,thisexampledoesn'trequire(orthereforeprove)this.It's
aweaktest,whichdoesn'treallyexplainwhat'sgoingon.
Page334,inappropriateanalogy(WindowsExplorer)
"YoumayhavenoticedthatWindowsExplorersorts"File20"before"File5"."
Noitdoesn'tI'vejusttried.Itdidatonepoint,butWindowsXPintroducedasmarter
versionofExplorerwhichhasanaturalsortorderitappliesacertainamountofsemantic
intelligencetofilenames.
Page334,unexplainedsubtlety(stringconcatenation)
Here'ssomecodewhichisgivenasanexampleofstringconcatenation:
StringMyString="Hello,"+"World!"
Thetextimpliesthatthe+operatorhereisjustashorthandforcallingString.Concatbutin
thiscasethecompilerperformstheconcatenationat
compiletime,
soString.Concatisn't
executedatall.
51

Page337,terminology(immutable)
"Mostofthevaluetypesinthe.NETFrameworkareimmutable,whichmeansthatwhenyou
assignanewvaluetothem,theCLRwillactuallycreateanewinstanceofthetypeand
throwtheoldoneaway."
That'snotwhat"immutable"meansatall.ReadEricLippert'sblogfora
detaileddiscussion
ofvariouskindsofimmutability
.
Page337,technicalerror(strings)
(Inthecontextofvaluetypes.)
"Theexception,ofcourse,isStrings,whichcansometimesbevery,verybigindeed."
ExceptthatStringisn'tavaluetype.
Page337,technicalerror(mutability)
"TheStringBuilderclassisareferencetype,andlikeallreferencetypes,itismutable."
No,referencetypesare
not
allmutable.System.Stringisprettymuchthecanonicalexample
ofanimmutablereferencetype.
Page339,disagreement(strengthof.NET'sdate/timeAPIs)
"ButIwarnyou,evenwiththeexcellentsupportthe.NETFrameworkprovides,handling
datesandtimesisalwaystricky."
IagreethatworkingwithdatesandtimescanbetrickybutIstronglydisagreewiththe
claimthat.NET'ssupportis"excellent".Ifitwereexcellent,Iwouldn'thavestartedthe
Noda
Time
project.Pleasereadmyblogpostentitled
"What'swrongwithDateTimeanyway?"
for
moredetailsofhowthe.NETdate/timesupportisfarfromexcellent.
Page339,technicalerror(meaningofDateTimeOffset)
"TheDateTimeOffsetrepresentsaparticulardateortimeinaparticularplace."
No,DateTimeOffsetknowsnothingabout
place.
Itrepresentsaninstantintimewithan
associatedlocaloffsetfromUTC,butthatoffsetmaybevalidforthatinstantinmultiple
placeswithdifferenttimezones.
Page343,terminology(Juliandates)
"Whenyouhearsomeonetalkingabout"Juliandates",theyalmostcertainlymeanadatein
themonth,day,yearformatcommonintheUnitedStates"
I'veneverhearditusedtomeanthat.I'veusuallyhearditwithameaningofsomethinglike
"thenumberofdayssincetheJulianepochof
January1,4713BC"andpotentiallysome
othermeanings,butnothingaboutjustamonth/day/yearformat.
Page345,disagreement(powerofTimeSpan)
Whentalkingaboutperiodsoftime:
"Allthattediumgoesawaywiththe.NETFrameworkTimeSpanstructure."
Noitdoesn'tTimeSpanisfineifyouonlycareaboutunitswhichneverchangeinlength
hours,minutes1etc.ButtryfindingouthowmanymonthsarebetweentwoDateTimevalues,
1

Dependingonwhichtimesystemyouuse,minutesandhoursdon'thavetobeconstanttimeeither,
duetoleapseconds.Inpractice,Idon'tbelievethat.NEThasanyhandlingbuiltinforleapseconds.

52

anditbecomesconsiderablytrickier.

(NodaTimedoesn'teither.)Thisisasourceofsomerelieftobehonest,asIfindleapseconds
incomprehensible.Mostbusinessapplicationsreallydon'tneedtocareaboutthem.A
day
cansensibly
besaidtonotbe24hoursthough,duetodaylightsavingtimechanges.That'sonlyappicablewhenyou
startconsideringtimesinaparticulartimezonethough.Dateandtimeis
really
complicated...

53

Chapter11
Page357,terminology(awfuluseof"set")
Theword"set"hasaveryclearmeaningwithincomputerscience,whichisverymuch
not
thesameastheauthor'suse.A"set"canonlycontainanyparticularelementonce,andis
usuallyunordered.Inthischapter,theauthoristalkingaboutcollectionsofallkindsnotjust
sets.Theexcuseof"theframeworkhasatypecalledCollection"doesn'treallywashwhen
theframework
also
hastypescalledISet,HashSetandSortedSetwhichfollowthe
traditional
meaningoftheword"set".Thismisappropriationoftheword"set"isjustasking
fortrouble.
Page359,technicalerror(arraymutability)
"Arraysareimmutable,likeStrings."
Nothey'renot.They'rereallynot.The
size
can'tbechangedafteryou'vecreatedone,but
youcanmutatethecontentstoyourheart'scontent:
int[]x=newint[2]
x[0]=5
x[1]=10
x[0]=15
Page359,technicalerror(resizingarrays)
"ItispossibletochangethesizeofsingledimensionarraysusingthestaticResize()
method."
Noit'snot.Thatdoesn't
actually
changethesizeofanexistingarray.Itcreatesa
new
array
andcopiesthecontentsoftheoldoneintothenewone,whichisn'tthesamethingatall.
Page359,technicalerror(arrayequivalentofStringBuilder)
"There'snoArrayequivalentofStringBuilder"
Wellthat'sprettymuchwhatList<T>andArrayListare,really.LikeStringBuilder(oratleast
oldimplementationsofStringBuilder)theymaintainabuffer,allowingyouto"resize"thelist
byaddingorremovingelements,onlycopyingwherenecessary.It'sreallyaprettystriking
similarity.

Page359,technicalerror(brokencode)
Thecodeatthebottomofpage360isbroken:
String[][]Menu={
newString[]={"a","b"},
newString[]={"one","two","three"},
newString[]={"x","y","z","omega"}
}
Problems:
Theinappropriateuseof=
Notrailingsemicolon.
Fixedcode:
54

String[][]Menu={
newString[]{"a","b"},
newString[]{"one","two","three"},
newString[]{"x","y","z","omega"}
}
Page361,typo(brokencode)
Morebrokensamplecode:
String[]Weekend=newString[2]
Weekend[0]="Saturday"
Weekend[1]"="Sunday"
Thedoublequoteafter[1]shouldberemoved.
Page363,typo(brokensyntaxdescription)
Thesyntaxdescriptionofforeachatthetopofpage363ismissingaclosing)onthefirst
line.
Page364,nastycode(ifconditionreturntrueelsereturnfalse)
Here'sapatternwhichcropsuprepeatedly,andfirstshowsup(thatInoticed)onpage364:
BooleanIsWeekend(StringtheDay)
{
if(theDay=="Saturday"||theDay=="Sunday")
returntrue
else
returnfalse
}
NormallyI'dsuggestchangingsomethingoftheform"if(condition)returnxelsereturny"
into"returncondition?x:y"butinthiscaseit'sevensimpler:
BooleanIsWeekend(StringtheDay)
{
returntheDay=="Saturday"||theDay=="Sunday"
}
Noneedforanifstatementoranythinglikeit.Thiscropsupagainandagain,anditmakes
mewinceeverytime.
Page367,technicalerror(arraysarereferencetypes)
"ButtheArrayisavaluetype,andassuchisimmutable."
Asmentionedbefore,arraysaren'timmutableandarraytypes(includingArrayitself)are
definitelyreferencetypes,notvaluetypes.
Page367,oddexplanation(authordoesn'tknowaboutArray.IndexOf?)
(AboutArrayList)
"...andbecausetheelementsareObjects,youcansearchthesetwithoutusingapredicate"
Justlikeyoucanwitharrays,using
Array.IndexOf
.Maybethere'sadifferentpointbeing
madehere,butifsoit'snotclear.

55

Page370,technicalerrors(useofArrayListindexervsAddreadercontribution)
Theanswerstotheexerciseonpage369
implies
thatthiscodewillcreateanArrayListand
thensetthethirditemto"Hello":
ArrayListMyAL=newArrayList(10)
MyAL[2]="Hello"

ThatwillactuallyfailwithanArgumentOutOfRangeExceptiononthesecondline.Theauthor
isn'tdistinguishingbetweenthelist's
capacity
(whichis10)anditsactual
size
(whichis0to
startwith).Youcan'tuseTheArrayListindexerto
add
newitemstoalist,onlytochangethe
valueofelementswithintheexistingrange.We'dhavetocallAddatleastthreetimes(or
populatethelistinanotherway)beforeusingtheindexerlikethis.

Asimilar(butveryslighltydifferent)mistakeoccurswiththenextpartoftheexercise:
'Insert"World"asanewitemattheendoftheMyAL'
Thistimethecorrectanswerisgiven:
MyAL.Add("World")
butthere'sacommentbyit:
'Youcouldalsohaveusedsomethinglike
MyAL[MyAL.Count1]="World"
butthat
wouldbefarmorecomplicated'

Thatwould
not
haveaddedanewitemtotheendofthelistitwouldhave
replaced
thefinal
elementofthelist(orfailedifthelistwasempty).
Page371/372/374,technicalerror(HashtablevsDictionary)
TheauthorappearstothinkthatkeysinaHashtabledon'thavetobeunique.Thetextinthe
bookissomewhatunclearaboutthedifferencebetweenkeysandhashcodes.Page371
hasthisinalabel:

"TheHashtableandDictionarystoreitemsinkey/valuepaiors.ThekeysofaDictionarymust
beunique.Hashcodesdon'thavetobe,butit'sbestiftheyare."

Anexercisethenasksthereadertoconsidertherightcollectiontomodelrealworlditems,
withthesedescriptions:
"Arolodexhasonecardforeveryphonenumber."
"Adictionaryhasasingleentryforaword,butawordcanhavemultiplemeanings."

Theanswergivenis:
"ARolodexislikeaDictionary,whileadictionaryislikeaHashtable."

Alaterexercisegivesthisasaquestiontobefixedin:
"ThemaindifferencebetweenaHashtableandaDictionaryisthatthekeyofaDictionary
mustbe:"

Thefirstlabel
could
beputdowntojustaconfusingdescription(possiblyhintingathash
codecollisions),buttherestsuggestthattheauthorthinksthere'sarealdifferenceherein
56

termsofkeyrequirements.Thereisn't.

BothDictionary<TKey,TValue>andHashtablecan
storeasinglevalueperkey,wherekeysarecomparedforequalityusingEqualsand
GetHashCode(optionallyviasomethinglikeIEqualityComparer).
Page377,confusion(generics)
Theuseofthewords"generic"and"generics"areveryconfusinghere:
"Instantiatingageneric"
ageneric
what
?
"Genericsarealsoakindofparameter"
thissoundsliketheauthoristalkingabouttype
parameters,ratherthan(say)generictypesorgenericmethods.
"Noticethe<T>.That'sthesyntaxforagenericparameter."
Thisshoulddefinitelybe
"generictypeparameter."
Page378,technicalerror(numbersoftypeparameters)
TheexercisereferstoDictionary<T>,SortedDictionary<T>andSortedList<T>.Allofthese
types
really
havetwotypeparameters:Dictionary<TKey,TValue>,SortedDictionary<TKey,
TValue>andSortedList<TKey,TValue>.
Page380,technicalerror(misunderstandingofHashSet<T>)
"ThistypeislikeaDictionary,buttheAdd()methodtakesjustthevalueandcalls
GetHashCode()togeneratethekey."
ThisisafundamentalmisunderstandingofwhatHashSet<T>isabout.Yes,hashcodesare
usedbutnotasuniquekeys.ConceptuallyaHashSet<T>justhaselements,andthehash
codesoftheelementsareusedtomakecheckingtoseewhetherthesetcontainsany
candidateelementreallyquick.
Page380,technicalerror(misunderstandingofSortedList<T>)
"ThistypeislikeaSortedDictionary,butyouhavetoprovideacustomroutinetocompare
thekeys."
Noyoudon't.You
can
,butyoudon'thaveto.Thedifferenceismostlyintermsoftheinternal
datastructuresandthecorrespondingperformancecharacteristics.

57

Chapter12
Page397,typo
Thedescriptionofencapsulationincludes"encapsulatin"inthesecondline.
Page400,technicalerror(codesample)
TheFinancialDetailsclassatthebottomrightofpage400containsareadonly
automaticallyimplementedproperty:
publicDecimalAccountBalance{get}
Thiswon'tcompile.
Page400,badpractice(inappropriatemutability)
TheFinancialDetailsclass(whichisasomewhatvaguenametostartwith)allowsthename
ofthebankandtheaccountnumbertobemutated.Ican'timagineasituationwherethis
wouldbeagoodidea.
Page401,confusionovercasting
Page401startswithaclaimwhichsoundsveryodd:
"Polymorphismisn'tthesameascasting.Whenyoucastatypetoanother,itbehaveslike
thenewtype.Thecodethat'sexecutedisthatofthetypetowhichitiscast,nottheoriginal
type."
That'snot
generally
trueinparticularit'snottruewhenitcomestovirtualmembers,
assumingthecastisactuallyperformingareferenceconversion.However,the"truth"ofthis
isdemonstratedusingonememberhidinganotherwhichisrarelyagoodidea,andrarely
comesupinwelldesignedcodeinmyexperience.Giventhatthispagedoesn'treally
explainanythingaboutoverridingetc,onewould
expect
thatthiscodewouldprint
System.String:
Object x = (Object) "this is a string";
Console.WriteLine(x.ToString());
(Thecastisobviouslyunnecessaryhere,butit'sjusttocomplyabsolutelywithwhat'swritten
inthebook.)HereareadercouldreasonablyexpecttheToStringmethodcalltoexecutethe
codeintheObjectimplementation,whichreturnsthenameofthetypeoftheobject.Of
course,itdoesn'tbecauseToStringisoverriddeninString.
Page402,missingbackreference
"We'vealsoseenthattheObject.GetType()method(inheritedbyeverytypeinthe.NET
Framework)returnsaninstanceoftheTypeclass"
Idon'trememberseeingthatanywhere...wasitremovedintheeditingprocess?
Page403,invalidcode(try/catchwithoutbraces)
Thecodeatthebottomofpage403ismissingbraces:
try
ISomethingnewThing=(ISomething)thing
catch
thrownewArgumentException("Can'tusething")
58

Bracesaren'toptionalfortry/catchstatements.
Page403,invalidcode(missingclosingbrace)
Thecodeatthebottomofpage403ismissingaclosingbraceforthe"else"statement.
Page404,invalidcode(missingclosingbrace)
Thecodeisstillmissingabraceinthe"answer"versiononpage404,althoughit'snotclear
which
braceismissing,asthefinalclosingbracegivenisn'talignedwithanyopeningbrace.
Page406/407,invalidcode(missing"class"keyword)
Allsevenclassdeclarationsonpages406and407aremissingthe"class"keyword,e.g.
publicsealedRecipe
{
}
Page406,invalidcode(methodmissingbracesentirely)
TheTabsToTspsmethod(whichwouldbebetternamedTablespoonsToTeaspoonsinmy
view)doesn'thaveanybracesatall,andsoisinvalid.
Page407,invalidcode(classshouldbeabstract)
TheRecipeclassatthetopofpage407containsanabstractmethod,somustbedeclared
abstract.
Page407,invalidcode(methodsmissingreturntypes)
TheRecipeandRecipeChildclassesatthebottomofpage407containDoSomething
methodswhicharedeclaredwithoutareturntype.
Page408,technicalerror(staticclassesandmethods)
"Intheory,astaticclasscanbeinheritedandastaticmethodcanbeoverridden,butbest
practicedictatesthattheyshouldalsobesealed."
No,you
can't
derivefromastaticclass(specsection10.1.1.3),youcan'toverrideastatic
method(specsection10.6.4)andyoucan'tsealeitherofthem(sections10.1.1.3and10.6).
Page409repeatsthiserror.
Page408,terminology(inheritingvsoverriding)
"Sealedmemberscannotbeinherited"
Yes,sealedmembers
are
inheritedtheyjustcan'tbeoverridden,whichisaverydifferent
matter.
Page408,terminologyandatypo("replacing"withnew,andoverridesvsoverride)
"Aclasswithvirtualmembersprovidesadefaultimplementation,butthememberscanbe
replacedinclassesthatinheritfromitusingtheneworoverrideskeywords"
Using"new"to
hide
amemberdoesn't
replace
it.Theimplementationisstillpresentandwill
beusedbyanythingusingacompiletimetypeofthebaseclass.That'scompletelydifferent
to"override"whicheffectively
does
overridetheimplementation(althoughstillavailablevia
nonvirtualbase.Foo()calls,ofcourse.)

59

Additionally,inC#thekeywordisoverride,notoverrides.Isuspectthisisacutandpaste
errorfromtheVBversionofthebook.
Page409,technicalerror(singletonpattern)
Inthecontextofwhenthestatickeywordisuseful:
"Whenthereshouldonlyeverbeasingleinstanceoftheobject.Thisiscallerdthesingleton
pattern.The.NETFrameworkApplicationclass,forexample,providesmethodsand
propertiesthatletyoumanageyourapplicationasawhole.Sincethere'sonlyeverone
instanceoftheapplicationitselfwithintheapplicationscope,Applicationisastaticclass."
Astaticclassis
not
anexampleofthe
singletonpattern
.Thesingletonpatternenforcesthat
onlya
single
instanceofthetypeisevercreated.Thatinstanceisthenusedwithnormal
instancemembers.Astaticclassenforcesthatthereare
no
instancesofthetype.See
my
articleonthesingletonpattern
forhowit's
actually
implementedin.NET.
Page409,badpractice(globalvariables)
"sometimesyouneedcertainvaluestobeavailabletoeveryobjectintheapplication.The
nameofthecurrentuser,forexample,ortheuser'sinterfacepreferencesaregood
examplesofthiskindofinformation.Astaticclassisagoodoptionforstoringthiskindof
information."
Ifit'sreallyadependencyofeverytype,theninjectaninstance
as
adependencyintoevery
typethatwayit'sreallyclearthatit'sadependency,andyouincreasetestability.Ican'tsee
whythe
businesslogic
ofanapplicationshouldcareabouttheuser'sinterfacepreferences,
forexampleorindeedwhymostofanapplicationislikelytocareaboutthenameofthe
currentuser.

Globalstateisalmostalwaysaheadache,andshouldbeavoidedwhereverpossible.
Page409,incompleteness(extensionmethods)
OneoftheusesI
do
likeforstaticclassesistohostextensionmethodswhicharen't
mentionedonpage409,butshouldbeinmyview.
Page411,disagreement(abstractclassmembers)
"Anabstractclassisverylikeaninterface.Itdefinesthemembersthatmustbeimplemented
byaninheritingclass,butdoesn'tusuallyprovideanyimplementation."
Onthecontrary,inmyexperienceanabstractclassusuallyprovidesimplementationsof
manymembers,onlyleavinga
few
abstractpossiblytobeusedbytheconcrete
implementations,asperthe
templatemethodpattern
.Anabstractclasswhichdoesn'tdefine
any
implementationwouldbequiteunusual.
Page412,disagreement(usefulnessoftheclassdesigner)
"WheretheClassDesignerreallycomesintoitsownwhenworkingwithabstractclassesis
inimplementingthenecessarymembersintheirdescendants.Simplyrightclickaninheriting
classandchooseImplementAbstractClassfromtheIntellisensemenu."
Orjustdeclarethebaseclassinthenormalcodeeditor,putthecursorintheabstractclass
nameandhitCtrlPeriod...there'sreallynoneedtogetadesignerinvolvedhere.

60

Page412,invalidandbadcode(missingclasskeyword,badnamingconventions)
Thecodeonpage412attemptstodeclareapublicabstractclass"myClass"withpublic
properties"myProperty"and"myAbstractProperty".Allofthesenamesviolate.NETnaming
conventions,andtheclassdeclarationdoesn'tincludethe"class"keyword,makingitinvalid
tostartwith.
Page415,terminology("semiabstractclass")
There'snosuchtermas"semiabstractclass"inC#.Theimplicationinthetextthatan
abstractclassforces
all
memberstobeoverriddenisincorrect.Anabstractclassdoesn't
evenhavetohave
any
abstractmembersifit'sdeclaredtobeabstract,it'sabstract.
Page417,poorexample
Thecodeexamplewhichdemonstratesthefirstuseofanoverriddenmethodisapoorone.
(MyChildderivesfromMyParentMyParentdeclarestheSayHellomethodandMyChild
overridesit.)
MyChildx=newMyChild()
x.SayHello()
ThiswouldinvoketheSayHello()methodinMyChildwhetheritwasoverridingthebase
classimplementation
orhidingit.
Itwouldbeamuchbetterexampleifitactuallyshowed
polymorphisminaction:
MyParentx=newMyChild()
x.SayHello()
Page419,badnaming
Justlikepage412,theclassesonpage419allviolate.NETnamingconventions.(Theydo
includethe"class"keywordthough.)
Page419,terminology(overridablevsinheritable)
"Itmightseemthatonlybeingabletomarkamethodassealedwhenyouusetheoverride
keywordisalimitation,butinfactthedefinitionofDontTouchMe()inmyNewaboveis
effectivelysealed.Doyouknowwhy?Whatkeywordwouldyouneedtoaddtomakeit
inheritable?"
Again,themethodwillbeinheritedbyanyderivedclassanyway.Itjustcan'tbeoverridden.
Seesection10.3.3ofthespecificationforwhatisinheritedinaclass.
Page421and422,technicalerror(extensionmethodsdon'thavetobepublic)
Whendescribinghowtowriteextensionmethods,thebooktalksaboutdeclaringapublic
staticclassandpublicstaticmethods.Bothofthesecouldbeinternalinsteadextension
methodsdon'thavetobepublic.Thiserrorisrepeatedonpage422,with:
"Theclassandthemethodmustbothbepublicandstatic."
(They
do
havetobestatic,butnotpublic.)
Page421,uncleardescription
"Thefirstparameterofthemethodmustbethenameoftheclassthemethodextends,
precededbythekeywordthis."
That'sanoddwaytodescribeit,inmyview.Iwouldusesomethinglike:
61

"Anextensionmethodmusthaveatleastoneparameter.Simplyaddthe"this"keyword
beforethetypeofthefirstparametertomakeit'extend'thattype.Notethatthefirst
parametercan'tbe'ref'or'out'parameter."
(Notethatthetypedoesn'thavetobeaclass.)
Page421,terminology(usingdirective,notusingstatement)
"Afteryou'vewrittentheextension,writetheusingstatementandanexampleofcallingthe
extensionmethod"
Thisshouldbeusing
directive
.
Page422,technicalerror(invalidcode)
Theexampleofanextensionmethoddeclarationlookslikethis:
publicstaticvoidPrintRecipeCard(thisRecipe)
Theparameterdoesn'thaveaname,soisinvalid.
Page422,terminology(namespacesaren'treferenced)
"Tocallthemethod,you'llneedtoreferencethenamespace"
Here"reference"soundsmorelikeaddingan
assembly
reference.Ausingdirective
imports
thenamespace(aspersection7.6.5.2oftheC#spec:"Ifnamespacesimportedbyusing
namespacedirectivesinthegivennamespaceorcompilationunit[...]"
Page422,terminology(extensionmethodscan't"override")
"Youcannotredefineamethodusingextensionmethods.Thecompilerwillalwaysgive
precedencetotheinstancemethod,soyouroverridewillsimplyneverbecalled."
Theword"override"ismisleadinghere"extensionmethod"wouldbe
much
better,asan
extensionmethodcannevereven
try
tooverrideamethod.(Staticmethodscan'tusethe
overridemodifieratall.)

62

Chapter13
Page429,disagreement(codeduplicationimpact)
"Ifthere'sanybitofcodethatappearsinmorethanoneplace,you'vegotasmellyproblem"
That'sanoverstatementtomymind.Inparticular,itcanleadtoartificiallytryingtomake
thingslookthesame(oftenviaanabuseofinheritance)whenthey'rereallynot.Onemotto
ofmycurrentteamleaderisthat"thingsaredifferentuntilthey'vebeenprovedthesame"
ashumanswe'realways
looking
forpatterns,andwe'realltoofondoffindingthemwhen
they'renot
really
present.

Theriskofhavingtochangesomelogicinmorethanoneplaceisveryrealbutsoisthe
riskofhavingonepieceoflogicwhichactuallyrepresentstwooperationswhichmerely
start
off
doingthesamething.Whenyoulaterwanttomakethosetwooperationsdo
different
things,youcanendupinarealmessifyou'veonlygotonepieceofcodetorepresentboth
ofthem.

I'mnotsuggestingcutandpastewillynilly,butjustthathavingthesamelogicintwoplaces
isn't
necessarilyasmell,asitallowsindependentevolutionoftwodistinctoperations.
Page429,disagreement(commenting)
Anotherinstanceofanearlierdisagreement:
"Youshouldwritecodethatmakescommentsseemunnecessary.(Butcommenteverything
anyway.)"
Iwouldsayyoushouldtrywheneverpossibletowritecodethatmakescomments
actually
unnecessary.Codewhichhascommentsforeveryoperation,howeverobvious,isvery
tedioustoreadandmaintainandthecommentscangetoutofsyncwithrealityremarkably
quicklyunlessyou'reverycareful.
Page437/438,invalidcode(IntegerinsteadofInt32)
Themethodonpage437(and438)usesaparametertypeofIntegeritshouldbeInt32.
Page437/438,poornamingandpossiblyinvalidcode
Thecodeonpage437(and438)usesavariablecalled"servingsModifier"whichis
describedwith"servingsModifiercontainstheamountforasingleserving"butit's
initialized
as:
servingsModifier=this.Servings/servings
Problems:
Thatlookslikea
scalingfactor
tomenotan"amount"ofanything.
Thevariableisn'tdeclaredinthemethodit'snotclearwhetherit'smeanttobean
instancevariable,orwhetherthisisjustinvalidcode.
BothServingsandservingsareintegers,soiftheexistingvalueofServingsis(say)
24andyouaskfor47servings,you'llendupwithaservingsModifierof1,which
reallyisn'tdesirable.
Page437/438,poormodelling
63

Afterthepreviouslinecomesthisloop:
foreach(RecipeItemingrinItems)
{
ingr.Amount*=servingsModifier
ingr.GetIngredientNutrition()
}
Problems:
Thismodifiestheexistingrecipeitwouldbemuchbetterinmyviewtocreateanew
instanceofRecipewiththescaledvalues.It
may
evenbeworthhavingtwoseparate
classesonefortherecipe"template"andonefortherecipe"instance"thatwewant
toprint,execute,whatever.Theyfeelconceptuallydifferenttomeforexample,it
mightmakesensetomakethe"instance"versionhaveaconceptofhowfarwe've
gotthroughthelistofsteps.
It'susingintegerarithmetic,withabunchofproblems(Amountisanint).Thisisa
separateinstanceoftheproblemshowninthepreviousitem.
It'snotclearwhattheGetIngredientNutritionmethoddoes,butusingamethod
prefixedwithGetbutignoringthereturnvalueseemslikeaverybadideatome.
EitherthisshouldbeRecalculateIngredientNutrition,oritshouldbeanonvoid
methodandthereturnvalueshouldbeused.
Thenewnumberofservingsisneverstoredsoifyouhavearecipewithaninitial
valueofServingsof1,andyourepeatedlycallRecalculateRecipe(2)you'llendup
doublingtheingredientquantitieseverytime.
Whileit'spossiblethattheseproblemsarementionedlater(Idon't
think
theyare)they
shouldn'tbelefttostandwithoutawarninghere,inmyview.
Page437/438,codeformatting
Thebracewhichclosesthe"if"statementonbothpage437and438isindentedtoofar.
Page443,terminology
"youhavetocreateaStringorInt16(whichareconcreteclasses,afterall)"
Int16isn'taclass,it'sastruct.Concrete
type
wouldbecorrectthough.
Page443445,confusion(dependencyinversionandprogrammingtointerfaces)
It'sentirelypossiblethatIdon'tunderstand
dependencyinversion
,butthesepages
look
like
they'remistakentome.I'mmorefamiliarwith"
dependencyinjection
"and"
inversionof
control
".I'mnotgoingtoclaimtobeanysortofauthorityontherelationshipbetweenthese
three,butthedescriptiongivenseemsincorrecttome.

WehavetwoclassesClientClassandConcreteClasswhichareinitiallyshownlikethis:

64


Tostartwith,it'snotclearwhat'sgoingonhere.DoesClientClassjust
create
aninstanceof
ClientClass,ordoesthe":"reallyrepresentinheritance(asinanormalclassdeclaration)?

There'salabelof
"Whenaclientclassinstantiesaconcreteclass,itisdependentuponit.If
ConcreteClasschanges,ClientClassneedstobe(attheveryleast)recompiled."

Thatdoesn'treallyclarifythediagramformeandit'salsoincorrectinthatiftheAPIof
ConcreteClassdoesn'tchange(justtheimplementation)thenClientClassshouldn'tneedto
berecompiled.

Theimprovedversion(i.e.afterapplyingdependencyinversion)lookslikethis:

ThelabelforClientClasssays:
"Thedependencyisinvertedwhenbothclassesdependon
anabstraction"
butit'snotclearhowthosedependenciesareexpressed.I'dexpect
ClientClassto
use
ontheinterface(i.e.accessthemembersoftheinterface,givenan
implementation)andConcreteClassto
implement
theinterface.

Thismakesit
look
likeClientClassismeantto
implement
theinterfacebutsurelyitshould
justbe
using
theinterface(e.g.asthetypeofaninstancevariablewithintheclass).It's
entirelypossiblethatthisiswhattheauthormeant,butthe"ClientClass:ISomeInterface"
part
suggests
thatitimplementstheinterface.

Beingacodeorientedkindaguy,I'dhavefoundthisclearer(withsomedescription,of
course):
65


Badcode,beforetightlycoupled,inflexible,andhardtotest:
publicclassSomeDependency{...}

publicclassClient
{
privatereadonlySomeDependencydependency

publicClient()
{
dependency=newDependency()
}

//Codeusingdependency
}

Bettercode:typeofdependencyisabstracted,actualinstanceisinjected,allowingfor
alternativeimplementationsinproduction,and
testdoubles
fortesting.

publicinterfaceISomeDependency{...}

publicclassSomeDependency:ISomeDependency{...}

//Maybeatsomepoint...
publicclassAnotherImplementation:ISomeDependency{...}

publicclassClient
{
privatereadonlyISomeDependencydependency

publicClient(ISomeDependencydependency)
{
this.dependency=dependency
}
//Codeusingdependency
}
Nowit'sclearwheretheinterfacecomesin,howtheclientusestheinterface,howthe
concreteclassimplementstheinterfaceetc.SomeextratextcoulddescribeIoCcontainers,
potentiallynotthatthey'rerequiredtousethispattern,ofcourse.
Page448,codeformattingandparametertype
Themethodatthebottomofpage448isshownas:
ChangeServings(Integer
desiredServings)
{
//do nothing
66

}
ThishasthesameproblemwesawearlierofusingIntegerinsteadofInt32,andforclarity
theparameternameshouldbemovedtothesamelineastherestofthedeclarationthere's
plentyofroom.

Page451,namingconventions
Iknowit'sonlymeanttobedemonstratingtheLawofDemeter,butthisshouldstillusemore
conventionalnames,inmyview(ideallywitharealisticexample,suchascustomer
addresses):
aFriend=newMyFriend()
aFriend.aFriendlyProperty=3
aFriend.aFriendsFriend=newaFriendsFriend()
(Asanaside,IfeeltheimportanceoftheLawofDemeterisoftenoverstated.It'sworth
bearinginmind,butit'sverycontextsensitive.)
Page467,typo
TheinterfaceshownintheclassdiagramisnamedIYieldBehaviors(plural)butinthetextit's
singular(asitshouldbe).Thesamemistakeoccursonpage469.
Page477,technicalerrororlackofclarity
"Becauseadelegatedefinesonlyamethodsignature,anyclassthatexposesamethodwith
thecorrectsignaturecanrespondtoanevent."
Theword"exposes"herecould
imply
thatthemethodhastobepublicorinternal.Itonly
needstobevisibletowhichevercodecreatesthedelegateinstanceit'squitecommonto
useprivatemethodsfordelegates.

There'salsothematterofanonymousfunctions(lambdaexpressionsandanonymous
methods),butthat'smoreamatterofcompleteness.
Page478,lackofclarity(conventionvsrequirementsforevents)
"ThesecondargumentpassedtoaneventhandlerisaninstanceofSystem.EventArgs."
That'scertainlytheconvention,butit'snotactuallyrequiredforevents.
Page478,technicalerror(delegaterequirements)
"Alldelegateshavethesamebasicpattern:theyaredeclaredaspublic,returnvoid,and
havetwoarguments."
Notethatthisistalkingabout
delegates,
notevents.Evenbearingconventionsinmind,that
statementiscertainlynottruefordelegates.Theydon'tneedtobepublic,theycanhave
differentreturntypes,andanynumberofparameters.
Page478,incompleteness(eventdeclarationsyntax)
"OfcourseyouneedtodeclaretheeventsotheCLRknowsaboutit.Thesyntaxissimple:
publicevent<DelegateType><EventName>
That's
one
waytodoit(declaringa
fieldlikeevent)
althoughitdoesn'thavetobepublic,of
course.Eveniftheauthordoesn'twanttogointothelongerdeclarationsyntax,itwouldbe
bettertoatleastacknowledgeitsexistence.
67

Page478,badcode(eventraisingmethod)
Thiscodeisprovidedforraisinganevent:
protectedvoidOn<EventName>(<EventName>Argse)
{
<EventName>(this,e)
}
ThatwillfailwithaNullReferenceExceptioniftherearenosubscriberstotheevent.More
idiomaticcodewouldbesomethinglike:
protectedvoidOnSomeEvent(EventArgse)
{
EventHandlerhandler=SomeEvent
if(handler!=null)
{
handler(this,e)
}
}
(Adjustaccordingtodelegatetypeandeventname,ofcourse.)
Page479,badcode(publiceventhandler)
Theeventhandlermethodshowninbullet1ofpage479ispublic.Thisisveryrarelyagood
ideaaneventhandlermethodshouldalmostneverbecalledorotherwisereferredto,apart
fromtheeventsubscriptioncodeitself,whichisusuallywithinthecontainingtype.It's
thereforebettertomakeitprivate.
Page479,technicalerror(delegateconstructor)
"Theconstructorforaadelegatetakethemethodnameasitsonlyparameter."
Notreally.The
delegatecreationexpression
inquestionusesamethodgroup,butthat
nameisn'tpassedtoaconstructorassuch.Thecompilerdealswiththetranslation,
basically.Seesection7.6.10.5oftheC#specformoredetails.
Page479,incompleteness(onlytheC#1.1delegatecreationexpressionisgiven)
ThiscodeisgiventocreateaninstanceofEventHandlerandassignittoavariable:
EventHandlermyDelegate=newEventHandler(MyEventHandler)
FromC#2onwards,youdon'tneedtobethisverbose:
EventHandlermyDelegate=MyEventHandler
Thiscanbeusedforeventsubscriptionaswell.Thisisn'tshownanywhereinthebookasfar
asIcantell.Forexample,thecodeonpage480canbesimplifiedto:
myEvent+=MyEventHandler
Theotherproblemshighlightedabove(apubliceventhandlerandanunsafe"raising"
method)arealsopresentonthecompleteexampleinpage480.
Page491,disagreement(roleofSilverlight)
Silverlightisdescribedlikethis:
"SilverlightiscloselyrelatedtoWPF.ItrunsovertheWeb(asareplacementforWeb
Forms),onthedesktop(withsomelimitations)andonmobiledeviceslikeWindowsPhone.
Ifyouned[sic]todeployyourapplicationonmultipleplatforms,Silverlightisprobablyyour
68

bestoption."
Idon'tthinkit'sagoodideatotalkaboutSilverlightactingasareplacementforWebForms.
ASP.NETMVCisthetechnologywhichbestfitsthatdescription,inmyviewandit'salso
probablythebestbetforatrulyportablesolution.That'sareplacementintermsofachieving
thesameaim(agenuinelyportablewebapplication)withabettertechnologystack.
Changingfromawebapptoarichclientapplication(whetherit'sSilverlight,Flashor
somethingsimilar)isamorefundamentalshiftthanoneimplementationstackreplacing
another.
P491,typo
Asshownabove,"ned"shouldbe"need".

69

Chapter15
Page514,confusingcomment
"...haveyounoticedthatXAMLisreallysmartaboutinterpretingvaluetypes?InC#you
havetobereallycarefulaboutusing1.0tospecifyaDoubleratherthananInteger[...]"
LeavingasidetheuseofIntegerinsteadofInt32forthemoment,it'snotclearwhatbenefitis
beingclaimedhere.I'm
glad
thattheC#compilerwillflaguptheuseofafloatingpointliteral
beingassignedtoavariablewithanintegertypeitkeepsmycodeclearer.IfIwantthe
integer1,I'llwrite1ratherthan1.0.Ifthis
is
thepointtheauthorwastryingtomake,I
disagreewithitifit'snot,thenI'mjustconfusedaboutwhatshewastryingtosay.
Page514,VBism
Theabovequotecontinueslikethis(fromthestartofthatsecondsentence)
"
InC#youhavetobereallycarefulaboutusing1.0tospecifyaDoubleratherthanan
Integer,or#01/01/01#foradate."
The"#01/01/01#"partreallygivesawaythatthiswaseithercutandpastefromtheVB
versionofthebook,ortheauthorwasatleastthinkinginVBwhenshewrotethis.C#hasno
literalsyntaxforDateTimevalues.
Page521,typo(Ithink)
(AbouttheChildrenandParentproperties)
"Youcanusethesepropertiestonegotiateupanddownthelogicaltree."
Itfeelslikethisshouldprobablybe
navigate
ratherthan
negotiate.
It'spossibletheauthor
reallydidmeannegotiatethough.

70

Chapter16
Page535,illegibletextduetobitmaprendering
Thediagramwhichmakesupthemajorityofpage535isrenderedasabitmapforsome
reasonandit'sbeenrenderedatarelativelylowresolution,whichleavessomeofthe
labelsveryhardtoread.(Mostdiagramsdon'thavethisproblem,althoughtheoneonpage
554isn'tgreateither.)
Page545,arrowsaremisaligned
Onpage545there'sasortof"logicalscreenshot"containingfiverectangles.Therearefive
arrowswhicharemeanttoshowwhichthreeareTextBoxelementsandwhichtwoare
Rectangleelementsbutsomeofthearrowspointintoemptyspace,andtwopointtothe
sameelement.
Page561,unexplainedreferencetonullablevaluetype
Page561talksabouttheresultofShowDialog():
"Toopenawindowasadialog,youusetheShowDialog()method,andyouhavetocapture
theresultinanullableBoolean.(Ithastobenullablebecausenotallwindowswithreturna
result.)"
Idon'tbelievenullablevaluetypesarecoveredanywhereinthebook.Page126implies
they'llbecoveredinchapter10,butotherthantheword"Nullable"appearingfaintlyinone
diagram,Ican'tseeanyexplanationofthem.
Page579/580,badpractice(suggestingtheuseofGetType()
Fromtheexerciseonpage579:
"Ourrecipehierarchyhastwolevels.You'llonlywanttoaddanewtabiftheuser
doubleclicksasecondlevelitem[...].Howdoyouthinkyoucancheckthat?(Hint:
remembertheGetType()method?)"
Thesuggestedsolutiononpage580is:
"YoucantestforParent.GetType().Name=="TreeView"."
That'sbrittleintermsof:
Inheritance(i.e.asubclassofTreeViewshouldprobablystillcount)
Susceptibletotypos(hardcodinganameasastring)
Namespaceambiguous(soaparentwhichwasaTreeViewfromadifferent
namespacewouldstillcountisthatreallydesirable?)
Nullsensitive(itwillthrowanexceptionifParentisnull)Idon'tknowwhether
Parentever
will
benull,admittedly.
Using"is"insteadwouldfixalloftheseproblemsbutfundamentallythisfeelslike
somethingweshouldn'tbeaskingthe
UI
anywayitshouldbeaboutthe
data,
shouldn'tit?
I'mnotafrontendprogrammerbyanymeans,butthisjustfeelslikeabitofahack.Maybe
it'sthewaythatthingsworkinWPF(inwhichcaseatleastusethe"is"operator)butI'd
ratherhaveacleanersolution,suchthateachitemhadeventhandlersattachedwhichwere
appropriateforthekindofdataitwasdisplaying.
(Thiscodeisthenpresentonpage586,aspartofafullerexample.)
Page586587,uglycode(useanobjectinitializer)
71

Muchofthecodeonpages586and587isjustsettingpropertiesandaddingelementsto
collections.Thesearebothbesthandledusingtheobject/collectioninitializersyntax
introducedinC#3andagain,I'darguethatifroomwastootighttojust
add
information
aboutobject/collectioninitializers,thereareplentyoftradeoffsI'dhavebeenhappytomake
inordertofindroomforthem.

72

Chapter17
Page592,typo(threeratherthantwo)
"Therearethreedifferencesinthefieldassociatedwithadependencyproperty"
Therearethentwobulletpoints,leavingthereaderwonderingwhatthethirddifferenceis.
Page592,confusingdescription
(Thisisinthesamesection,talkingabout
fields
.It'stheseconddifference.)
"Itisdeclaredpublic,staticandreadonly,insteadofprivate,whichisconsideredbest
practiceforanormalproperty."
Thefinalwordshouldprobablybe"field"ratherthanproperty,andit'snotentirelyunusualto
haveapublicstaticreadonlyfieldString.Emptyissuchafield.

What
isn't
mentionedisthatwe'rereallycomparingappleswithorangesherea"normal
field"storesthedatavalueitself(orareferencetotheobjectcontainingthevalue).Inthe
caseofadependencyproperty,thevalueofthefieldisanextralevelofindirectionit's
metadata
abouttheproperty,really.
Page593,unnecessarilyverbosecode
Thefield+propertyimplementationsnippetatthetopofpage593wouldbemore
idiomaticallyimplementedusingasinglelineautomaticallyimplementedproperty.
Page597and598,typo(bulletnumbering)
Thenumberedlistsonbothpage597and598contain"3"twiceperlist,andno"2".
Page615,incompletedescription(delegates)
"Rememberthatadelegateissimplyadatatypethatholdsamethod,asopposedto,say,a
StringoraninstanceoftheRecipeItemclass."
Whilethisprobablywouldn'tbetherightplacetobringitupanyway,delegatescanhold
referencesto
multiple
actions,notjustone.(TheseparationbetweenSystem.Delegateand
System.MulticastDelegateisaredherringasinpracticealldelegatetypesderivefrom
MulticastDelegate.)
Page615,invalidcode(typoofperiodforsemicolon)
Notonlydoestheexampleatthebottomofpage615usethenasty"if(condition)returntrue
elsereturnfalse"pattern,butitfailstodosocorrectlyduetoatypothere'saperiodafter
"returnfalse"insteadofasemicolon.
Page617,typo
Inthefirstparagraph:
"Likethecoercevaluemethod,themethodreferencebythePropertyChangedCallback
delegate"
Isuspect"reference"shouldbe"referenced"here.
Page618620,opportunityformethodgroupconversions
73

ThecallstothePropertyMetadataconstructorsareanothergreatexampleofwhereusing
methodgroupconversionswouldbesimpler.Forexample,thiscodeonpage620:
Register("TestDp",
typeof(String),
typeof(MainWindow),
newPropertyMetadata("nothing",
newPropertyChangedCallback(OnTestDpChanged),
newCoerceValueCallback(CoerceTestDp)),
newValidateValueCallback(ValidateTestDp))

canbesimplifiedto:
Register("TestDp",
typeof(String),
typeof(MainWindow),
newPropertyMetadata("nothing",OnTestDpChanged,CoerceTestDp),
ValidateTestDp)

Page619,layout
Forsomereasonthere'sarectanglearoundthesecondparagraphoftextonpage619.I
don'tthinkit'smeanttobethere.

74

Chapter18
Page637,unnecessaryToString()calls(personalpreference)
Thisisamatteroftaste,butpersonallywhenI'malreadyinthecontextofstring
concatenation,Idon'tbotherwithexplicitToStringcalls.(I'mawareoftheboxingconcerns
forvaluetypes,butthat'srarelysignificantinmyexperience.)
Sothiscode(indentedandwrappedasperthebook):
StringBuildereventDetailsSB=newStringBuilder()
eventDetailsSB.AppendLine("Event:"+e.RoutedEvent.Name)
eventDetailsSB.AppendLine("Sender:"+sender.GetType().ToString())
eventDetailsSB.AppendLine("Source:"+e.Source.GetType().ToString())
eventDetailsSB.AppendLine("Original:"+e.OriginalSource.GetType().
ToString())

wouldbecome:
StringBuildereventDetailsSB=newStringBuilder()
eventDetailsSB.AppendLine("Event:"+e.RoutedEvent.Name)
eventDetailsSB.AppendLine("Sender:"+sender.GetType())
eventDetailsSB.AppendLine("Source:"+e.Source.GetType())
eventDetailsSB.AppendLine("Original:"+e.OriginalSource.GetType())

Alternatively,Imightuseamorefluentapproach:
StringBuildereventDetailsSB=newStringBuilder()
.AppendFormat("Event:{0}",e.RoutedEvent.Name).AppendLine()
.AppendFormat("Sender:{0}",sender.GetType()).AppendLine()
.AppendFormat("Source:{0}",e.Source.GetType()).AppendLine()
.AppendFormat("Original:{0}",e.OriginalSource.GetType()).AppendLine()

Page641,typo(parametername)
"...youcanusetheAddHandler()methodandpasstrueastheHandledEventsToo
parameter"
Thenameoftheparameteris"handledEventsToo"withalowercase"h"(asper.NET
namingconventions).
Page642,disagreement(diagnostics)
TheauthorrecommendsusingmessageboxesfordiagnosticsConsole.WriteLineis
shown,buttheauthor'spreferenceisformessageboxes:
"personallyIfindit[Console.WriteLine]noeasiertocallandalittleclutteredtoread."
Thatsuggeststhatthesediagnosticsarealwaysremovedbeforeshippingwhichmeans
theycan'tbeusedtotraceproblemsencounteredinthefield.Icertainlywouldn'twant
messageboxespoppingupallovertheplaceasauser!

There'samuchbettersolutionthaneitherofthese:useaproperloggingframework(e.g.
log4net
)whichcanbeusedbothindevelopment
and
inaproductionsystem,withthelevel
ofdiagnosticoutput(andthedestination)controlledatexecutiontimeviaaconfigurationfile
ratherthanhardcoded.
Page644,technicalerror(Ibelieve)
75

"Ifyou'reusingoneofthe.NETFrameworkargumentclasses,youcanusethe
RoutedEventHandlerasyoureventdelegate,butifyoudeclareanewargumenttype,you'll
alsoneedtodeclareadelegate."
Whatwouldgowrongifyoujustusethegeneric
EventHandler<TEventArgs>
?That'swhat
it'stherefor...betweenthatandtheFunc/Actiondelegatefamilies,Irarelyfindmyself
declaringmyowndelegatetypesthesedays.
Page645,typo(notinvalid,justodd)
Themethodonpage645isdeclaredas
protectedOnMyCustomEvent()
ThespacebetweenOnMyCustomEventand()shouldberemoved.
Page652,terminology
InalabelreferringtoApplicationCommands,EditingCommands,NavigationCommands,
MediaCommandsandComponentCommands.
"TheroutedcommandsdefinedbytheFrameworkarestaticclasses."
I'dsaythey're
exposed
viastaticpropertiesinstaticclasses.Thecommandsthemselves
aren'tstaticclassesthey'reinstancesofRoutedUICommandandthelike.
Page661,incompleteness(exposingroutedcommands)
"Whileit'spossibletoimplementanewcommandtype,usuallyyou'llcreateaninstanceof
RoutedCommandorRoutedUICommandasapublicstaticproperty."
Thisshouldbeapublicstatic
readonly
property.Makingthepropertyread/writewouldbea
reallybadidea.

76

Chapter19
Page676,confusingcomment
AftersettingtheA/R/G/BpropertiesonaColorseparately:
"Didyouworkoutthecasttobyte?YoucouldhaveusedFromARGB(),butthecodewould
havebeenreallylongbecauseofallthosecasts."
Thecastsareneededeitherway,soit'snotlikeseparatingthemreallyreducesthelengthof
thecode.Iftheproperties
are
tobesetseparately,I'dpersonallyuseanobjectinitializer
instead.
Page683,codeformatting
TheclosingbraceontheShowGradient_Clickmethodismysteriouslyindentedabout8
spaces.
Page683,codeclarity
Thecodeonpage683wouldbealotclearerinmyviewwithjudicialuseoftheconditional
operator.

77

Chapter20
Page715,typo
Thethirdparagraphonpage715starts"YoucouldcreateaClassthatdeclares[...]"I
suspectthat"Class"shouldbe"class"here.(ThismaybeaVBismthatcreptin.)
Page736,unfairC#vsXAMLcomparison
InanattempttoshowhowmuchclearerXAMLcanbethanC#(whichI'msureistruein
manycases),theauthorshowsthisC#code:
if(this.IsEnabled==true)
{
if(this.IsSelected==true)
this.FontWeight=FontWeights.Bold
else
this.FontWeight=FontWeights.Normal
}
else
this.FontWeight=FontWeights.Light
Thecommentthataccompaniesthisincludes:
"Nestedifstatementsarevery,verycomplexandeasytomessup."
Sodon'tdothat.Aconditionalworkswellhere,eitherbyinvertingthe"enabled"condition:
this.FontWeight=!IsEnabled?FontWeights.Light
:IsSelected?FontWeights.Bold
:FontWeights.Normal

orbyexplicitlystatingbothpartsoftheconditionineachcase:
this.FontWeight=
(IsEnabled&&IsSelected)?FontWeights.Light
:(IsEnabled&&!IsSelected)?FontWeights.Bold
:FontWeights.Normal
Thisinvolvesredundantpropertychecking,butisveryexplicitaboutthesituationsunder
whicheachfontweightisused.

Anotheralternativeistocreateamethodtodeterminetherightfontweight,andcallthatit
allowsyoutoperformthedeterminationseparatelyfromtheassignmenttotheFontWeight
property.

Onceyou'reusedtojustreadingdownthissortofpattern,itbecomesveryeasytofollow.
PersonallyIwouldfind
any
oftheseeasiertogetmyheadroundthantheXAMLshownon
page736.
Page747,layoutissues(stretcheddiagram)
Thediagramatthebottomofpage747appearstobestretchedhorizontally,whichlooks
odd.
Page750,typo(WidthshouldbeHeight)
78

Theexplanationoftheexerciseansweronpage750includes:"Ifyoudon'texplicitlysetthe
Widthproperty,itdoesn'thaveavalue[...]"IbelievethisshouldbetheHeightproperty,
giventherestoftheexplanationandthecode.
Page754,layoutissues(swappedscreenshots)
Therearetwoscreenshotsonpage754,eachofwhichisnexttoabitofXAMLbutI
think
thescreenshotsarethewrongwayround.

79

Chapter21
Page779,layoutissue(arrowtailoverlaystext)
Thearrowinthetopdiagramofpage779overlapsthetext,sothe"100%"ofthelabellooks
odd.

80

Chapter22
Page802,typo(unmatchedparenthesis)
Themiddleparagraphonpage802includesanopenparenthesiswhichisneverclosed.
Page803,typo(caseofXmlDataProvider)
ThetextreferstoanXMLDataProviderelement,whichIbeliveshouldbeXmlDataProvider.
Page806,typo(unmatchedbrace)
ThesecondBindingshownonpage806appearstobemissingaclosingbrace:
{BindingSource={RelativeSourceMode={x:staticRelativeSource.Self},
Path=FontSize}

Page813,confusionorbadpractice
Whenfindingoutaboutbuildingabindablecollection,we'refirstinstructedtocreateaclass
whichderivesfromObservableCollection<T>.However,it'snotclear
why
wesupposedly
needtocreateanewclassratherthanjustusingObservableCollection<T>directly.No
membersofObservableCollection<T>arebeingoverriddeninthecodesamples,andI
generallyprefer
not
tocreateclassesjustforthesakeofit.Ican'ttellwhetherthisisjust
pointlessorwhetherthere'ssomerealreasonforit.

(Thesampleshowingtheconstructorofthenewclassalsoexplicitlycallsbase()withalabel
of"Youneedtocallthebaseclass'sconstructor"
implying
thatyouneedtodosoexplicitly.)
Page813,badand/orinvalidcode
Theexamplecontinueswiththissamplecode:
publicMyBindableitems=newMyBindable()
MyBindable.Add(newMyType())
It'snotclear:
Wherethiscodeshouldappear
Whywe'dwanta
public
,mutablefield(ick)
WhyAddisbeingcalledontheclass(MyBindable)ratherthanthefield.
Page813,invalidcode
Theexamplecontinuesinthenextsnippetwith:
this.DataContextMyBindable
Isuspectthisshouldbeanassignment,andprobablyusingthefieldratherthanthenameof
thecollectiontype.
Page831,longwindedcode
Theconvertercodeonpage831wouldbesimplerusingtheconditionaloperatorandimplicit
callstoToString.
Page831,codeformatting
TheXAMLnearthebottomcontainsaWindow.Resourceselementwhoseclosingtagis
81

indentedmorethanitshouldbe.
Pages834and835,badcode(inappropriateuseof"as")
Bothpages834and835containcodewhichusesthe"as"operatorandthenunconditionally
dereferencestheresult.Here'sthecodeonpage234:
Ingredienting=objasIngredient
return(ing.OnHand>50)
Ifyou'resocertainthatthevalue
really,really
shouldbeoftherighttype,acastismore
appropriatethanusing"as"thatwayifyou'rewrong,yougetanInvalidCastException
insteadofalessinformativeNullReferenceException.

82

Vous aimerez peut-être aussi