MikeMcGrath
C#Programming
IneasystepsisanimprintofInEasyStepsLimited16HamiltonTerrace.HollyWalk.LeamingtonSpaWarwickshire.CV324LYwww.ineasysteps.com
Copyright©2016byInEasyStepsLimited.Allrightsreserved.Nopartofthisbookmaybereproducedortransmittedinanyformorbyanymeans,electronicormechanical,includingphotocopying,recording,orbyanyinformationstorageorretrievalsystem,withoutpriorwrittenpermissionfromthepublisher.
NoticeofLiabilityEveryefforthasbeenmadetoensurethatthisbookcontainsaccurateandcurrentinformation.However,InEasyStepsLimitedandtheauthorshallnotbeliableforanylossordamagesufferedbyreadersasaresultofanyinformationcontainedherein.
TrademarksAlltrademarksareacknowledgedasbelongingtotheirrespectivecompanies.
Contents
1GettingstartedIntroducingC#InstallingVisualStudioExploringtheIDEStartingaConsoleprojectWritingyourfirstprogramFollowingtherulesSummary
2StoringvaluesCreatingvariablesReadinginputEmployingarraysCastingdatatypesFixingconstantsSummary
3PerformingoperationsDoingarithmeticAssigningvaluesComparingvaluesAssessinglogicExaminingconditionsSettingprecedenceSummary
4MakingstatementsBranchingwithifSwitchingbranchesLoopingforLoopingwhileIteratingforeachSummary
5DevisingmethodsCreatingfunctionPassingargumentsOverloadingmethodsRefactoringcodeSummary
6Handlingstrings
DiscoveringstringfeaturesManipulatingstringsJoiningandcomparingstringsCopyingandswappingstringsFindingsubstringsFormattingstringsFormattingdatestringsSummary
7AccessingfilesWritingafileAppendingtoafileReadingtextandlinesStreaminglinesManipulatinginputandoutputSummary
8SolvingproblemsDetectingreal-timeerrorsFixingcompile-timeerrorsDebuggingcodeSettingbreakpointsCatchingrun-timeerrorsGettinghelpSummary
9CreatingobjectsEncapsulatingdataCreatingmultipleobjectsInitializingclassmembersInheritingclasspropertiesCallingbaseconstructorsHidingbasemethodsDirectingmethodcallsProvidingcapabilityclassesEmployingpartialclassesSummary
10ControllingeventsStartingaFormsprojectAddingvisualcontrolsWritingfunctionalcodeGatheringtextentriesTickingoptionboxesShowingusermessagesCallingsystemdialogsCreatingapplicationmenusMakingmenusworkImportingaudioresourcesSummary
11BuildinganapplicationPlanningtheprogramAssigningfixedpropertiesDesigningthelayoutSettingdynamicpropertiesAddingruntimefunctionTestingtheprogramPublishingtheapplicationSummary
12TargetingdevicesStartingaUniversalprojectInsertingpagecomponentsImportingprogramassetsDesigningthelayoutAddingruntimefunctionTestingtheprogramAdjustingtheinterfaceDeployingtheapplicationSummary
1
Gettingstarted
WelcometotheexcitingworldofC#programming.ThischapterintroducestheVisualStudioIntegratedDevelopment
EnvironmentandshowsyouhowtocreatearealWindowsapplication.
IntroducingC#InstallingVisualStudioExploringtheIDEStartingaConsoleprojectWritingyourfirstprogramFollowingtherulesSummary
IntroducingC#TheintroductionoftheMicrosoft.NETframeworkattheProfessionalDevelopersConferenceinJuly2000alsosawMicrosoftintroduceanewprogramminglanguagecalledC#(pronounced“see-sharp”).Thenamewasinspiredbymusicalnotationwherea#sharpsymbolindicatesthatawrittennoteshouldbeasemitonehigherinpitch.ThisnotionissimilartothenamingoftheC++programminglanguagewherethe++symbolindicatesthatawrittenvalueshouldbeincrementedby1.
• C#isdesignedtobeasimple,modern,general-purpose,object-orientedprogramminglanguage,borrowingkeyconceptsfromseveralotherlanguages–mostnotablytheJavaprogramminglanguage.Consequently,everythinginC#isaclass“object”with“properties”and“methods”thatcanbeemployedbyaprogram.
• C#isanelegantand“type-safe”programminglanguagethatenablesdeveloperstobuildavarietyofsecureandrobustapplications.YoucanuseC#tocreateWindowsclientapplications,XMLwebservices,distributedcomponents,client-serverapplications,databaseapplications,andmuch,muchmore.
• C#isspecificallydesignedtoutilizetheprovenfunctionalitybuiltintothe.NETframework“classlibraries”.WindowsapplicationswritteninC#thereforerequiretheMicrosoft.NETframeworktobeinstalledonthecomputerrunningtheapplication–typicallyanintegralcomponentofthesystem.
Thesourcecodeofallexamplesinthisbookisavailableforfreedownloadatwww.ineasysteps.com/resource-center/downloads
TheMicrosoft.NETFrameworkEachversionoftheMicrosoft.NETframeworkincludesaunifiedsetofclasslibrariesandavirtualexecutionsystemcalledtheCommonLanguageRuntime(CLR).TheCLRallowstheC#languageandtheclasslibrariestoworktogetherseamlessly.
Tocreateanexecutableprogram,sourcecodewrittenintheC#languageiscompiledbytheC#CompilerintoIntermediateLanguage(IL)code.Thisisstoredondisk,togetherwithotherprogramresourcessuchasimages,inan“assembly”.Typically,theassemblywillhaveafileextensionof.exeor.dll.Eachassemblycontainsa“manifest”whichprovidesinformationaboutthatprogram’ssecurityrequirements.
WhenaC#programisexecuted,theassemblyisloadedintotheCommonLanguageRuntime(CLR),andthesecurityrequirementsspecifiedinitsassemblymanifestareexamined.Whenthesecurityrequirementsaresatisfied,theCLRperformsJust-In-Time(JIT)compilationoftheILcodeintonativemachineinstructions.TheCLRthenperforms“garbagecollection”,exceptionhandling,andresourcemanagementtasksbeforecallingupontheoperatingsystemtoexecutetheprogram:
AslanguageinteroperabilityisakeyfeatureoftheMicrosoft.NETframework,theILcodegeneratedbytheC#Compilercaninteractwithcodegeneratedbythe.NETversionsofotherlanguagessuchasVisualBasicandVisualC++.TheexamplesthroughoutthisbookdemonstrateVisualC#programcode.
Just-In-Timecompilationisalsoknownas“DynamicTranslation”.
Just-In-Timecompilationoccursduringprogramexecution,ratherthanpriortoitsexecution.
InstallingVisualStudioInordertocreateWindowsapplicationswiththeC#programminglanguage,youwillfirstneedtoinstallaVisualStudioIntegratedDevelopmentEnvironment(IDE).
MicrosoftVisualStudioistheprofessionaldevelopmenttoolthatprovidesafullyIntegratedDevelopmentEnvironmentforVisualBasic,VisualC++,VisualJ#,andVisualC#.WithinitsIDE,codecanbewritteninVisualBasic,C++,J#ortheC#programminglanguagetocreateWindowsapplications.
VisualStudioCommunityeditionisastreamlinedversionofVisualStudio,speciallycreatedforthosepeoplelearningprogramming.Ithasasimplifieduserinterfaceandomitsadvancedfeaturesoftheprofessionaleditiontoavoidconfusion.C#codecanbewrittenwithintheCodeEditorofeitherversionoftheVisualStudioIDEtocreateWindowsapplications.
BothVisualStudioandVisualStudioCommunityprovideanIDEforC#programmingbut,unlikethefully-featuredVisualStudioproduct,theVisualStudioCommunityeditioniscompletelyfreeandcanbeinstalledonanysystemmeetingthefollowingminimumrequirements:
Component: Requirement:
Operatingsystem
Windows10Windows8/8.1Windows7ServicePack1WindowsServer2012/2012R2WindowsServer2008R2SP1
CPU(processor) 1.6GHzorfaster
RAM(memory) 1024MB(1GB)minimum
HDD(harddrive) 4GBavailablespace,5400RPMspeed
VideoCard DirectX9-capable,andascreenresolutionof1024x768orhigher
TheVisualStudioCommunityeditionisusedthroughoutthisbooktodemonstrateprogrammingwiththeC#language,buttheexamplescanalsoberecreatedinVisualStudio.FollowthestepsoppositetoinstalltheVisualStudioCommunityedition.
TheNewiconpicturedaboveindicatesaneworenhancedfeatureintroducedwiththelatestversionofC#andVisualStudio.
OpenyourwebbrowserandnavigatetotheVisualStudioCommunitydownloadpage–atthetimeofwritingthiscanbefoundatvisual-studio.com/vs
Scrolldownthepagethenclickthebuttontodownloadavs_communityinstallerfile
Clickonthevs_communityfiletoruntheinstaller
Acceptthesuggestedinstallationlocation,thenclickNext
ChoosetheDefaulttypeofinstallation,thenclickInstalltobeginthedownloadandinstallationprocess
Choosingadifferentdestinationfoldermayrequireotherpathstobeadjustedlater–it’ssimplertojustacceptthesuggesteddefault.
TheVisualStudio2015installerallowsyoutoinstalljustthecomponentsyouneed.
Youcanre-runtheinstalleratalaterdatetoaddorremovefeatures.
ExploringtheIDEGototheStartmenu,thenselecttheVisualStudio2015menuitemaddedtherebytheinstaller:
SigninwithyourMicrosoftAccount,orregisteranaccountthensignin,tocontinue
ClicktheStartVisualStudiobuttontolaunchtheapplication
ThefirsttimeVisualStudiostartsittakesafewminutesasitperformsconfigurationroutines.
TheVisualStudioIntegratedDevelopmentEnvironment(IDE)appears,fromwhichyouhaveinstantaccesstoeverythingneededtoproducecompleteWindowsapplications–fromhereyoucancreateexcitingvisualinterfaces,entercode,compileandexecuteapplications,debugerrors,andmuchmore.
TheVisualStudioIDEinitiallyincludesadefaultStartPage,alongwiththestandardIDEcomponents,andlookslikethis:
Tochangethecolor,choosetheTools,OptionsmenuthenselectEnvironment,General,Colortheme.
StartPageelementsThedefaultStartPageprovidestheseusefulfeatures:
• Start–provideslinksyoucanclicktobeginanewprojectorreopenanexistingproject.
• Recent–convenientlylistsrecentlyopenedprojectssoyoucanquicklyselectonetoreopen.
• News–feedsthelatestonlinenewsdirectfromtheMicrosoftDeveloperNetwork(MSDN).
YoucanreturntotheStartPageatanytimebyselectingView,StartPageontheMenuBar.
VisualStudioIDEcomponentsTheVisualStudioIDEinitiallyprovidesthesestandardfeatures:
• MenuBar–whereyoucanselectactionstoperformonallyourprojectfilesandtoaccessHelp.Whenaprojectisopen,extramenusofProjectandBuildareshown,inadditiontothedefaultmenuselectionofFile,Edit,View,Debug,Team,Tools,Test,Analyze,Window,andHelp.
• Toolbar–whereyoucanperformthemostpopularmenuactionswithjustasingleclickonitsassociatedshortcuticon.
• Toolbox–whereyoucanselectvisualelementstoaddtoaproject.PlacethecursorovertheToolboxtoseeitscontents.Whenaprojectisopen,“controls”suchasButton,Label,CheckBox,RadioButton,andTextBoxareshownhere.
• SolutionExplorer–whereyoucanseeataglanceallthefilesandresourcecomponentscontainedwithinanopenproject.
• StatusBar–whereyoucanreadthestateofthecurrentactivitybeingundertaken.Whenbuildinganapplication,a“Buildstarted”messageisdisplayedhere,changingtoa“Buildsucceeded”or“Buildfailed”messageuponcompletion.
ThemenusareonceagaininTitleCase,ratherthantheALLCAPSstyleofthepreviousversion.
OnlineelementsoftheStartPagerequirealiveinternetconnection–ifthehyperlinksdonotappeartowork,verifyyourinternetconnection.
StartingaConsoleproject
GettingStarted
OntheMenuBar,clickFile,New,Project...,orpresstheCtrl+Shift+Nkeys,toopenthe“NewProject”dialogbox
Inthe“NewProject”dialogbox,selecttheInstalled,Template,VisualC#,ConsoleApplicationitem
EnteraprojectnameofyourchoiceintheNamefield–inthiscasetheprojectnamewillbe“GettingStarted”
ClicktheOKbuttontocreatethenewproject
LeavetheCreatedirectoryforsolutionoptioncheckedtocreateafoldernamedastheprojectname,andlocatedbydefaultinyourDocuments,VisualStudio2015,Projectsdirectory.
VisualStudionowcreatesyournewprojectandloadsitintotheIDE.Anew,tabbedCodeEditorwindowappears(inplaceoftheStartPagetabbedwindow)containingdefaultskeletonprojectcodegeneratedbyVisualStudio.
DragtheCodeEditorwindowtabtoundocktheCodeEditorwindowfromtheVisualStudioIDEframe
Thesourcecodeofallexamplesinthisbookisavailableforfreedownloadatwww.ineasysteps.com/resource-center/downloads
Theundockedwindowtitledisplaystheprojectname,andthetabdisplaysthefilenameofthecodeas“Program.cs”.
Thecodenamespaceisdeclaredusingyourchosenprojectname–inthiscaseit’s“GettingStarted”.
SelecttheView,SolutionExplorermenutoopenaSolutionExplorerwindowtodiscoveralltheitemsinyourproject
SelecttheView,PropertiesmenutoopenaPropertieswindow,thenselectanyitemintheSolutionExplorerwindowtoseeitspropertiesinthePropertieswindow
TheCodeEditorwindowiswhereyouwriteC#codetocreateanapplication.TheVisualStudioIDEhasnowgatheredalltheresourcesneededtobuildadefaultConsoleapplication.YoucanclicktheDebug,StartDebuggingmenutoseeVisualStudiobuildtheapplication,butitwilldonothinguntilyouaddsomecode.
YoucandragthetitlebarofanywindowtoundockthatwindowfromtheVisualStudioIDEframe.Whendragging,youcandropawindowonthe“guidediamond”(shownbelow)todockthewindowinyourpreferredposition.
Alternatively,youcanpresstheF5shortcutkeytostartDebugging.
WritingyourfirstprogramInordertocreateaworkingConsoleapplicationyouneedtoaddC#codetothedefaultskeletonprojectcodegeneratedbytheVisualStudioIDE:
Hello
OntheMenuBar,clickFile,New,Project,orpresstheCtrl+Shift+Nkeys,toopenthe“NewProject”dialogbox
Inthe“NewProject”dialogbox,selecttheInstalled,Template,VisualC#,ConsoleApplicationitem
EnteraprojectnameofyourchoiceintheNamefield–inthiscasetheprojectnamewillbe“Hello”
ClicktheOKbuttontocreatethenewprojectandseetheCodeEditordisplaythedefaultskeletonprojectcode
Positionthecursorbetweentheinnermost{}curlybrackets(braces),thenhitEntertoaddanewline
Onthenewline,preciselytypethisC#codeConsole.WriteLine(“HelloWorld!”);Console.WriteLine(“PressAnyKeyToContinue...”);
HitEntertoaddanothernewline,thenpreciselytypethisC#codeConsole.ReadKey();
Asyoutypethecodeasuggestionboxwillappear.Thisisthe“IntelliSense”feature.YoucanselectanitemtheninsertitintoyourcodebypressingtheTabkeyortheSpacebar.
TheMain()methodisautomaticallycalledwheneveraC#programisrun–toexecutetheinstructionscontainedwithinits{}braces.
Now,selectFile,SaveHello,orpresstheCtrl+Skeys,tosavethecompletedC#Consoleapplication
Then,selectthe StartbuttonontheToolbar,orpresstheF5key,tobuildandruntheapplication
AConsolewindowliketheoneshownaboveshouldnowappear,displayingatraditionalprogramminggreeting.
HitEnter,orclickthe Stopbutton,toclosetheapplicationandseetheConsolewindowdisappear
ToeditthedefaultConsolewindowcolorsandfont,right-clickitswindowTitlebarandchooseProperties.Forclarity,allotherConsolewindowscreenshotsinthisbookfeatureLucidaConsole14-pixelFontinblackScreenTextonawhiteScreenBackground.
CodeanalysisExaminationofthecodehelpstounderstandwhatishappening:
• usingSystem;ThisisadirectiveallowingtheSystem.ConsoleclassobjecttobewrittenwithouttheSystem.prefix.
• namespaceHello{}Thisisadeclarationthatcreatesauniquenamespacewrapperinwhichtoencloseyourprogram.
• classProgram{}Thisdeclarationcreatesa“Program”classinwhichtocreateyourownprogrampropertiesandmethods.
• staticvoidMain(string[]args){}ThisdeclarationcreatesastandardMain()methodinwhichtowriteyourC#code.
• Console.WriteLine(“HelloWorld!”);ThisisastatementthatcallsupontheWriteLine()methodoftheConsoleclasstooutputtextenclosedinquotemarkswithinitsparentheses.
• Console.ReadKey();ThisstatementcallsupontheReadKey()methodoftheConsoleclasstowaitforanykeytobepressed.
CodelistedthroughoutthisbookiscoloredtomatchthedefaultsyntaxhighlightcolorsoftheVisualStudioCodeEditor,foreasyrecognition.
CallingtheReadKey()methodisalittletricktokeeptheConsolewindowopenuntilyoupressanykey.Withoutthisstatementtheapplicationwouldoutputitsmessagethenimmediatelyexit.
FollowingtherulesAswithallprogramminglanguages,C#hasanumberofsyntaxrulesthatmustbepreciselyfollowedtoensurethecodeiscorrectlyformattedfortheC#compilertoclearlyunderstand:
• Case-sensitivity–C#isacase-sensitivelanguage,whichmeansthatuppercase“A”andlowercase“a”areregardedastotallydifferentitems.
• Termination–AllstatementsinC#languagemustbeterminatedbya;semicoloncharacter,justasallsentencesinEnglishlanguagemustbeterminatedbya.periodcharacter.Forexample:Console.WriteLine(“HelloWorld!”);
• Single-linecomments–Briefcommentsonasinglelinemustbeginwith//twoforwardslashcharacters.Forexample://Outputthetraditionalgreeting.
• Blockcomments–Extendedcommentsonmultiplelinesmustbeginwith/*forwardslashandasteriskcharacters,andmustendwiththereverse*/asteriskandforwardslash.Forexample:/*C#Programmingineasysteps.Gettingstartedwiththetraditionalgreeting.
*/
• Whitespace–Spaces,tabs,newlinecharacters,andcommentsareignoredbytheC#compiler,socanbeusedextensivelytoorganizecodewithoutperformancepenalty.
• Escapesequences–TheC#compilerrecognizes\nasanewlinecharacterand\tasatabcharacter,sothesecanbeusedtoformatoutput.Forexample:Console.WriteLine(“LineOne\nLineTwo”);
• Namingconventions–Aprogrammer-definedidentifiernameinC#codemaybeginwithan_underscorecharacteroraletterinuppercaseorlowercase.Thenamemayalsocontainanunderscore,lettersandnumerals.Forexample:classMyNo1_Class
• Keywords–TheC#languagehasanumberofkeywords(listedopposite)thathavespecialsyntacticmeaningandmaynotbeusedtonameprogrammer-defineditemsincode.
Itisrecommendedthatyoucommentyourcodetomakeitreadilyunderstoodbyothersorwhenrevisitingyourowncodelater.
TheWriteLine()methodautomaticallyaddsanewlineafteritsoutput.
C#ReservedKeywords
abstract as base bool
break byte case catch
char checked class const
continue decimal default delegate
do double else enum
event explicit extern false
finally fixed float for
foreach goto if implicit
in int interface internal
is lock long namespace
new null object operator
out override params private
protected public readonly ref
return sbyte sealed short
sizeof stackalloc static string
struct switch this throw
true try typeof uint
ulong unchecked unsafe ushort
using virtual void volatile
while
Ifyouabsolutelymustuseakeywordtonameaprogrammer-definedelement,itmay
beprefixedbyan@charactertodistinguishitfromthekeyword–butthisisbestavoided.
C#ContextualKeywords
add alias ascending async
await descending dynamic from
get global group into
join let orderby partial
remove select set value
var where yield
Contextualkeywordshavespecialsignificanceincertaincode.Forexample,getandsetinmethoddeclarations.
Summary• C#isanobject-orientedprogramminglanguagethatutilizestheprovenfunctionalityofthe
Microsoft.NETclasslibraries.
• TheC#compilergeneratesIntermediateLanguage(IL)codethatisstoredondiskalongsideresourcesinanassembly.
• TheCommonLanguageRuntime(CLR)examinesanassembly’ssecurityrequirementsbeforeJITcompilation.
• Just-In-TimecompilationtranslatesILcodeintonativemachinecodeforexecutionbytheoperatingsystem.
• MicrosoftVisualStudioprovidesafullyIntegratedDevelopmentEnvironment(IDE)forC#programming.
• AnewVisualC#ConsoleapplicationgeneratesdefaultskeletonprojectcodeintheVisualStudioCodeEditor.
• TheVisualStudioSolutionExplorershowsallfilesinaprojectandthePropertieswindowshowstheirproperties.
• C#codeneedstobeaddedtothedefaultskeletoncodeintheCodeEditortocreateaC#program.
• TheusingSystemdirectiveallowstheSystem.ConsoleclasstobewritteninthecodewithoutitsSystem.prefix.
• TheConsoleclasshasaWriteLine()methodthatcanbeusedtooutputaspecifiedtextstring,andaReadKey()methodthatcanrecognizewhentheuserpressesanykey.
• AC#programcanberunintheVisualStudioIDEbyselectingtheDebug,StartDebuggingmenu,orbyclickingtheStartbutton,orbypressingtheF5key.
• C#isacase-sensitiveprogramminglanguageinwhichallstatementsmustbeterminatedbya;semicoloncharacter.
• Single-line//commentsand/**/blockcommentscanbeincorporatedtoexplainC#programcode.
• C#haskeywordsthathavespecialsyntacticmeaning,socannotbeusedtonameprogrammer-definedcodeitems.
2
Storingvalues
ThischapterdemonstrateshowtostorevarioustypesofdatawithinaC#program.
CreatingvariablesReadinginputEmployingarraysCastingdatatypesFixingconstantsSummary
CreatingvariablesA“variable”islikeacontainerinaC#programinwhichadatavaluecanbestoredinsidethecomputer’smemory.Thestoredvaluecanbereferencedusingthevariable’sname.
Theprogrammercanchooseanynameforavariable,providingitadherestotheC#namingconventions–achosennamemayonlycontainletters,digits,andtheunderscorecharacter,butmustbeginwithaletter,underscore,[email protected]#keywordsmustbeavoided.It’sgoodpracticetochoosemeaningfulnamestomakethecodemorecomprehensible.
Tocreateanewvariableinaprogramitmustbe“declared”,specifyingthetypeofdataitmaycontainanditschosenname.Avariabledeclarationhasthissyntax:
data-typevariable-name;
Multiplevariablesofthesamedatatypecanbecreatedinasingledeclarationasacomma-separatedlistwiththissyntax:
data-typevariable-name1,variable-name2,variable-name3;
ThemostcommonC#datatypesarelistedinthetablebelow,togetherwithabriefdescriptionandexamplecontent:
DataType: Description:
int Anintegerwholenumber,e.g.100
char Asinglecharacter,e.g.‘A’
float Afloating-pointnumberof7-digitprecision
double Afloating-pointnumberof15-digitprecision
decimal Afloating-pointnumberof28-digitprecision
bool ABooleanvalueoftrueorfalse
string Astringofcharacters,e.g.“InEasySteps”
Variabledeclarationsmustappearbeforeexecutablestatements–sotheywillbeavailableforreferencewithinstatements.
Namesarecase-sensitiveinC#–sovariablesnamednum,Num,andNUMaretreatedasthreeindividualvariables.Traditionally,C#variablenamesarecreatedinalllowercasecharacters.
Charactervaluesofthechardatatypemustbeenclosedinsinglequotes,butcharacterstringsofthestringdatatypemustbeenclosedbetweendoublequotes.
Thedecimaldatatypeispreferredforstorageofmonetaryvalues.
Whenavalueisassignedtoavariableitissaidtohavebeen“initialized”.Optionally,avariablemaybeinitializedinitsdeclaration.ThevaluestoredinanyinitializedvariablecanbedisplayedusingtheWriteLine()method,whichwasusedheretodisplaythe“HelloWorld!”greeting:
Variables
OpentheVisualStudioIDE,thenstartanewConsoleApplicationprojectandnameit“Variables”
Positionthecursorbetweenthe{}curlybracketsoftheMain()method,thentypethiscodetonametheConsoleConsole.Title=“Variables”;
Next,preciselytypethesestatementstodeclareandinitializevariablesofcommonC#datatypescharletter; letter=‘A’; //Declaredtheninitialized.intnumber; number=100; //Declaredtheninitialized.floatbody=98.6f; //Declaredandinitialized.doublepi=3.14159; //Declaredandinitialized.
decimalsum=1000.00m; //Declaredandinitialized.boolflag=false; //Declaredandinitialized.stringtext=“C#IsFun”; //Declaredandinitialized.
Now,insertstatementstodisplayeachstoredvalueConsole.WriteLine(“charletter:\t”+letter);Console.WriteLine(“intnumber:\t”+number);Console.WriteLine(“floatbody:\t”+body);Console.WriteLine(“doublepi:\t”+pi);Console.WriteLine(“decimalsum:\t”+sum);Console.WriteLine(“boolflag:\t”+flag);Console.WriteLine(“stringtext:\t”+text);Console.ReadKey();
PressStarttoruntheapplicationandseethestoredvalues
Suffixftoafloatvalueandmtoadecimalvaluetodistinguishthemfromadoublevalue.
Theinclusionof\tinthestringisan“escapesequence”thatprintsatabintheoutput.The+symbolisa“concatenation”operator,whichaddsthestoredvaluetothestringforoutput.
ReadinginputInordertointeractwiththeuser,C#programswilltypicallyrequiretheusertoinputsomevalues.TheReadLine()method,acompaniontotheReadKey()method,canbeusedtoreaduserinput.UserinputwithintheConsolecanbeassignedtoastringvariablebytheReadLine()methodwhentheuserhitsEntertocompletealine.
ItisimportanttorecognizethattheReadLine()methodalwaysreadsinputasastringvalue.
Whenrequestinguserinput,it’spreferabletoprompttheuserwithoutaddinganewlineaftertherequest.ThisiseasilyachievedusingtheConsole.Write()method:
Input
OpentheVisualStudioIDE,thenstartanewConsoleApplicationprojectandnameit“Input”
Positionthecursorbetweenthe{}curlybracketsoftheMain()method,thentypethiscodetonametheConsoleConsole.Title=“Input”;
Next,preciselytypethesestatementstorequestuserinputforassignmenttoavariableConsole.Write(“PleaseEnterYourName:“);stringname=Console.ReadLine();
Now,addstatementstodisplayamessagecontainingthestoreduserinputvalueConsole.WriteLine(“Welcome”+name+“!”);Console.ReadKey();
PressStartorF5toruntheapplicationandseethestoreduserinputvaluedisplayedinoutput
Numericalvaluesinputbytheuserareassignedtothestringvariableascharacters–soarithmeticcannotbeperformedonthese.
Noticehowtwo+concatenationoperatorsareusedheretoinsertinputintoastring.
WhenyourequiretheusertoinputnumericalvaluesitisnecessarytoconvertthestringvaluesreadbytheReadLine()methodintonumericaldatatypes.TheSystem.Convertclassprovidesanumberofusefulmethodsforthispurpose,including:
Method: Returns:
Convert.ToInt32() A32-bitsignedinteger
Convert.ToDouble() Afloating-pointprecisionnumber
Convert.ToDecimal() Adecimalprecisionnumber
ThereisalsoausefulConvert.ToString()methodtotranslatevaluestostringtype.
ThestringvaluereadbytheReadLine()methodneedssimplytobespecifiedwithintheparenthesesoftheappropriatemethod:
Conversion
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Conversion”
TypethesestatementstorequestuserinputforconversionandassignmenttotwovariablesConsole.Write(“PleaseEnterANumber:“);
doublenum=Convert.ToDouble(Console.ReadLine());Console.Write(“NowEnterAnotherNumber:“);doublesum=
num+Convert.ToDouble(Console.ReadLine());
Now,addstatementstodisplayamessagecontainingthesumtotaloftheuserinputvaluesConsole.WriteLine(“Total=”+sum);Console.ReadKey();
PressStartorF5toruntheapplication,thenentertwovaluestoseetheconvertedinputaddedinoutput
Here,thesecondinputnumbergetsconvertedtoanumericalvaluebeforeadditiontothefirstinputnumber.
EmployingarraysAnarrayisavariablethatcanstoremultipleitemsofdata–unlikearegularvariable,whichcanonlystoreonepieceofdata.Thepiecesofdataarestoredsequentiallyinarray“elements”thatarenumbered,startingatzero.Sothefirstvalueisstoredinelementzero,thesecondvalueisstoredinelementone,andsoon.
Anarrayisdeclaredbystatingthedatatype,suffixedby[]squarebracketstodenoteanarray.Thisalonedoesnotinitializethearrayvariableinmemoryuntilanarray“instance”iscreatedbyspecifyinganelementsizeusingthenewkeyword,likethis:
data-type[]array-name=newdata-type[size];
Valuescanthenbeindividuallyassignedtoeachavailableelement:
array-name[element-number]=value;
Arraynumberingstartsatzero–sothefinalelementinanarrayofsixelementsisnumberfive,notnumbersix.Thisnumberingisknownasa“zero-basedindex”.
Alternatively,anarraycanbeinitializedandvaluesassignedtoeachelementwhenitisdeclaredbystatingvaluesforeachelementinacomma-separatedlist,groupedwithinbraces:
data-type[]array-name=newdata-type[size]{value,value,value};
Anyindividualelement’svaluecanbereferencedusingthearraynamefollowedbysquarebracketscontainingtheelementnumber.Forexample,toreferencethevaluewithinthefirstelement:
array-name[0]
Collectively,theelementsofanarrayareknownasan“index”.Arrayscanhavemorethanoneindex–torepresentmultipledimensions,ratherthanthesingledimensionofaregulararray.Multi-dimensionalarraysofthreeindicesandmoreareuncommon,buttwo-dimensionalarraysareusefultostoregrid-basedinformation,suchascoordinates.
Youcanonlystoredatawithinarrayelementsofthedatatypespecifiedinthearraydeclaration.
Tocreateamulti-dimensionalarray,the[]squarebracketsfollowingthedatatypeinthedeclarationmustcontainacommaforeachadditionalindex.Similarly,thesizeofeachindexmustbespecifiedasacomma-separatedlist,likethis:
data-type[,]array-name=newdata-type[size,size];
Valuescanthenbeindividuallyassignedtoeachavailableelement:
array-name[element-number,element-number]=value;
Aspecialforeachloopconstructallowsyoutoeasilyiteratethroughallelementsofanarray–seeherefordetails.
Alternativelyamulti-dimensionalarraycanbeinitializedandvaluesassignedtoeachelementwhenitisdeclaredbystatingvaluesforeachindexinacomma-separatedlist,groupedwithinbraces–inacomma-separatedgroupenclosedwithinbraces:
data-type[,]array-name=newdata-type[size]{{value,value,value},{value,value,value}};
Thenumberofspecifiedvaluesmustexactlymatchthespecifiedarraysizetoavoidanerror.
Anyindividualelement’svaluecanbereferencedusingthearraynamefollowedbysquarebracketscontainingtheelementnumberforeachindex.Forexample,toreferencethevaluewithinthefirstelementofthesecondindex:
array-name[1,0]
Arrays
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Arrays”
Next,typethisstatementtocreateastringarraystring[]cars=newstring[3]{“BMW”,”Ford”,”Opel”};
Now,typethisstatementtocreatea2-dimensionalarrayint[,]coords=newint[2,3]{{1,2,3},{4,5,6}};
AddstatementstodisplayoutputcontainingthestoredarrayelementvaluesConsole.WriteLine(“SecondCar:”+cars[1]);Console.WriteLine(“X1,Y1:”+coords[0,0]);Console.WriteLine(“X2,Y3:”+coords[1,2]);Console.ReadKey();
PressStartorF5toruntheapplicationandseethevaluesstoredwithinarrayelements
CastingdatatypesAvaluestoredinavariablecanbeforced(coerced)intoavariableofadifferentdatatypebyconvertingthevaluetoadifferenttype.Thisprocessisknownas“casting”andmaybeimplicitorexplicit.
Castingisalsoknownas“typeconversion”.
• ImplicitcastingisautomaticallyperformedbyC#inatype-safemannerwhenconvertingnumbersfromsmallertolargerprecisiondatatypes.Forexample,whenaddinganinttoadouble.
• Explicitcasting,ontheotherhand,requiresacastoperatortobeincludedinastatementtospecifythedatatypetowhichthevalueshouldbecast.Therequirednewdatatypemustbespecifiedinparenthesesprecedingthenameofthevariablecontainingthedatatobecast,soitssyntaxlookslikethis:
variable-name=(data-type)variable-name;
ThisisthetraditionalformofcastingthatisalsofoundintheCprogramminglanguage.Castingisoftennecessarytoaccuratelystoretheresultofanarithmeticoperationtopreventdataloss.Divisionofoneintegerbyanotherintegerwillalwaysproduceanintegerresult,whichmaybetruncated.Forexample,theintegerdivision7/2producesthetruncatedintegerresultof3.
Tostoretheaccuratefloating-pointresultwouldrequiretheresultbecastintoasuitabledatatype,suchasadouble,likethis:
doublesum=(double)7/2; //Sumis3.5
Theresultofdividinganintegerbyanotherintegeristruncated,notrounded–soaresultof9.9wouldbecome9.
Itshouldbenotedthatoperatorprecedencecaststhefirstoperand7intothespecifieddatatypebeforeimplementingthearithmeticoperation/2division,soeffectivelythestatementis:
doublesum=(double)(7)/2; //Sumis3.5
Bracketingtheexpressionas(7/2)wouldperformthearithmeticfirstonintegers,sotheintegerresultwouldbetruncatedbeforebeingcastintothefloatvariable–notthedesiredeffect!
doublesum=(double)(7/2); //Sumis3.0
SinglecharactervaluescanusefullybeexplicitlycasttoanintdatatypetorevealtheirASCIIcodevalue.Similarly,theprocesscanbereversedtorevealthecharactervalueofaninteger.
Cast
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Cast”
Typethesestatementstocreateandinitializeanintegervariableandadouble-precisionfloating-pointvariabledoublenum=10.5;intinteger=2;
Next,addstatementstoimplicitlycasttheintegervalueintoadouble-precisionvalue,anddisplaytheresultnum=num+integer;Console.WriteLine(“ImplicitCast:”+num);
Now,explicitlycasttheresultofanintegerdivisionintoadouble-precisionvalue,anddisplaythatresultnum=(double)7/integer;Console.WriteLine(“ExplicitCast:”+num);
CastanintegervalueintoachardatatypeanddisplayitsASCIIequivalentcharactercharletter=(char)65;Console.WriteLine(“CastInteger:”+letter);
CastacharactervalueintoanintdatatypeanddisplayitsASCIIequivalentcodenumberintascii=(int)‘A’;Console.WriteLine(“CastLetter:”+ascii);Console.ReadKey();
PressStartorF5toruntheapplicationandseethevaluescastintootherdatatypes
Removethe(double)castfromStep4toseetheresultbecometruncated.
ASCII(pronounced“askee”)istheAmericanStandardCodeforInformationInterchange,whichistheacceptedstandardforplaintext.InASCII,charactersarerepresentednumericallywithintherange0-127.Uppercase‘A’is65sothatintegervaluegetscastintoanintvariable.
FixingconstantsVariabledeclarationsexplicitlyspecifytheirpermissibledatatypeusingkeywords,suchasstring,int,ordouble,toensuretheprogramcannotaccidentallyassigninappropriatedata.Whereyouarecertainthiswillneveroccur,youmayusethevar(variant)keywordwhendeclaringavariable,toimplicitlyspecifyitsdatatypeaccordingtothedatatypeofitsinitialvalue.Inthiscase,theC#compilerwillautomaticallydeterminetheappropriatedatatype.ThevarkeywordismostusefultostoreavaluethatisotherthanofthestandardC#numerical,Boolean,orstringdatatypes.Allvariabledeclarationsmadeusingthevarkeywordmustassignaninitialvaluetoimmediatelydeterminethatvariable’sdatatype.
Declaringvariablesusingthevarkeywordcanmaketheprogramcodelessreadable,asitdoesnotindicatedatatypes.
Thedatatypeofanyvariablecanberevealedbydot-suffixingtheGetType()methodontothevariablename.Forexample,whereanumvariableisadoubledatatype,callingnum.GetType()willreturnaSystem.Doubleresult.
Whenastoredvalueisneverintendedtobechanged,a“constant”containercanbecreatedtosafeguarditfromchange.Itsdeclarationissimilartothatofavariable,butbeginswiththeconstkeyword.Alldeclarationsmadeusingtheconstkeywordmustassignaninitialvaluetoimmediatelyfixitsconstantvalue.
Multipleconstantvaluescanbedefinedinanenumeratorlistusingtheenumkeywordandaspecifiedidentifiername.Thiscreatesadatatypethatconsistsofacomma-separatedlistofnamedconstantswithin{}braces.Theenumeratorlisthasanunderlyingdefaultintvaluethatnumbersthelistnamesfromzero,muchliketheelementsinanarray.Anynamewithinthelistcanbereferencedbydot-suffixingittothelistname,anditsunderlyingvaluerevealedbycasting.
Anenumeratorlistcannotbedeclaredwithinanymethodblock,somustbedeclaredoutsidetheMain()method.
TheC#Enumclassprovidesseveralmethodstoworkwithenumeratorlists.Manyoftheserequirethedatatypeofthelistasanargumentsothiscanusefullybeassignedtoavarvariableby
specifyingthelistnameasanargumenttothetypeof()method.TheEnumclassGetName()methodcanrevealthenameataspecifiedindexposition,andtheIsDefined()methodcanbeusedtotestwhetherthelistcontainsaspecifiedname.Anenumeratorlistdeclarationmustbewrittendirectlywithintheprogramnamespaceorwithinaclassblock.
Constant
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Constant”
Typethisstatementwithintheclassblock,beforetheMain()methodblock,tocreateanenumeratorlistenumDays{Sat,Sun,Mon,Tue,Wed,Thu,Fri};
Now,turnyourattentiontotheMain()method,thendeclareandinitializeaconstantandavariableconstdoublepi=3.14159265358979;vardaysType=typeof(Days);
Next,addstatementstorevealtheconstant’sdatatypeanduseitsvalueforoutputConsole.WriteLine(“PiType:”+pi.GetType());Console.WriteLine(“Circumference:”+(pi*3));
Then,addstatementstodisplaythenameandindexpositionofthefirstitemintheenumeratorlistConsole.WriteLine(“\nFirstName:”+Days.Sat);Console.WriteLine(“1stIndex:”+(int)Days.Sat);
Finally,addstatementstodisplaythenameatthesecondindexpositionandtoquerytheenumeratorliststringname=Enum.GetName(daysType,1);Console.WriteLine(“\n2ndIndex:”+name);boolflag=Enum.IsDefined(daysType,“Mon”);Console.WriteLine(“ContainsMon?:”+flag);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheconstantvaluesinoperation
Theenumeratorlistcontainsnames,notstrings,sotheyneednotbeenclosedinquotemarks,butthenamemustbesuppliedasastringargumenttotheIsDefined()method.
Youmaywanttoavoidthevarkeywordwherepossibletobesureofvariabledatatypes.Forexample,withthelinevarid=getID();theassignedvalue(andthereforethevariabledatatype)couldbenumericorastring.
Summary• Avariablestoresadatavaluewithinthecomputer’smemory,andthevaluecanbereferenced
usingthatvariable’sname.
• Avariabledeclarationmustspecifythetypeofdataitmaycontain,andavalidprogrammer-specifiedname.
• CommonC#datatypesincludeint,char,float,double,decimal,bool,andstring.
• Variablesmustbedeclaredbeforetheycanbereferenced.
• Avariablebecomesinitializedwhenitisassignedavalue.
• TheConsole.ReadLine()methodcanbeusedtoassignuserinputtoavariable.
• TheConsole.WriteLine()methodaddsanewlineafteritsoutput,buttheConsole.Write()methoddoesnot.
• TheSystem.Convertclassprovidesanumberofusefulmethodstoconvertstringvaluestonumericaldatatypes.
• Anarrayvariablecanstoremultipleitemsofdatawithinsequentialelementsofazero-basedindex.
• Anarraydeclarationmustspecifythetypeofdataitmaycontain,followedby[]andaprogrammer-specifiedname.
• Anarrayisnotinitializeduntilanarrayinstanceiscreatedusingthenewkeywordtospecifydatatypeandelementsize.
• Valuescanbeassignedtoindividualarrayelementsusingthearraynameandtheelementindexnumber.
• Anarraydeclarationcanassignvaluestoallofitsarrayelementsasacomma-separatedlistofvalueswithin{}braces.
• Arrayscanhavemorethanoneindex,torepresentmultipledimensions,whereeachindexisseparatedbyacomma.
• Castingistheconversionofonedatatypetoanother.
• ImplicitcastingisperformedautomaticallybyC#.
• Explicitcastingisperformedbyincludingacastoperatorwithinastatement,tospecifytherequirednewdatatype.
3
Performingoperations
ThischapterintroducesC#operatorsanddemonstratestheoperationstheycanperform.
DoingarithmeticAssigningvaluesComparingvaluesAssessinglogicExaminingconditionsSettingprecedenceSummary
DoingarithmeticThearithmeticoperatorscommonlyusedinC#programsarelistedinthetablebelow,togetherwiththeoperationtheyperform:
Operator: Operation:
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus
++ Increment
-- Decrement
The%modulusoperatorisalsoknownasthe“remainder”operator.
The+operatorisdual-purpose–itisalsousedtoconcatenatestrings.
Theoperatorsforassignment,addition,subtraction,multiplication,anddivisionactasyouwouldexpect,butcaremustbetakentogroupexpressionswheremorethanoneoperatorisused–operationswithininnermost()parenthesesareperformedfirst:
a=b*c-d%e/f; //Thisisunclear.
a=(b*c)-((d%e)/f); //Thisisclearer.
Valuesusedwithoperatorstoformexpressionsarecalled“operands”–intheexpression2+3thenumericalvalues2and3aretheoperands.
The%modulusoperatorwilldividethefirstgivennumberbythesecondgivennumberandreturntheremainderoftheoperation.Thisisusefultodetermineifanumberhasanoddorevenvalue.
The++incrementoperatorand--decrementoperatoralterthegivennumberbyoneandreturntheresultingvalue.Thesearemostcommonlyusedtocountiterationsinaloop–countinguponeachiterationwiththe++incrementoperator,orcountingdownoneachiterationwiththe--decrementoperator.
The++incrementand--decrementoperatorscanbeplacedbeforeorafteravaluetodifferenteffect–placedbeforetheoperand(prefix)itsvalueisimmediatelychanged;placedaftertheoperand(postfix)itsvalueisnotedfirst,thenthevalueischanged.
Arithmetic
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Arithmetic”
Typethesestatementstocreateandinitializetwointegervariablesinta=8;intb=4;
Next,addstatementstooutputtheresultofeachbasicarithmeticaloperationConsole.WriteLine(“Addition:\t:”+(a+b));Console.WriteLine(“Subtraction:\t:”+(a-b));Console.WriteLine(“Multiplication:\t:”+(a*b));Console.WriteLine(“Division:\t:”+(a/b));Console.WriteLine(“Modulus:\t:”+(a%b));
Now,addstatementstooutputtheresultofapostfixincrementoperationConsole.WriteLine(“\nPostfix:\t:”+(a++));Console.WriteLine(“PostfixResult.....:\t:”+a);
Finally,addstatementstooutputtheresultofaprefixincrementoperation–forcomparisonwithpostfixConsole.WriteLine(“\nPrefix:\t:”+(++b));Console.WriteLine(“PrefixResult.....:\t:”+b);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheresultsproducedbyeacharithmeticoperator
Here,the\tescapesequenceisusedtooutputatabspace,andthe\nescapesequenceisusedtooutputadditionalnewlines.
Rememberthataprefixoperatorchangesthevariablevalueimmediatelybutapostfixoperatorchangesthevaluesubsequently.
AssigningvaluesTheoperatorsthatareusedinC++programmingtoassignvaluesarelistedinthetablebelow.Allexceptthesimple=assignmentoperatorareashorthandformofalongerexpressionsoeachequivalentisgivenforclarity:
Operator: Example: Equivalent:
= a=b a=b
+= a+=b a=(a+b)
-= a-=b a=(a-b)
*= a*=b a=(a*b)
/= a/=b a=(a/b)
%= a%=b a=(a%b)
The+=combinedoperatorisdual-purpose–itcanalsobeusedtoconcatenatestrings.
Intheassignmentexampleabove,wherea=b,thevariablenamed“a”isassignedthevaluethatiscontainedinthevariablenamed“b”–sothatisthenthevaluestoredintheavariable.Technicallyspeaking,theassignmentoperatorstoresthevalueoftheright-handoperandinthememorylocationdenotedbytheleft-handoperand,thenreturnsthevalueasaresult.
Itisimportanttoregardthe=operatortomean“assign”ratherthan“equals”toavoidconfusionwiththe==equalityoperatorthatisdescribedhere.
The+=combinedoperatorisusefultoaddavalueontoanexistingvaluethatisstoredintheavariable.Intheexampleabove,wherea+=b,thevalueinvariablebisaddedtothatinvariablea–sothetotalisthenthevaluestoredintheavariable.Thearithmeticoperationisperformedfirstwiththegroupedoperands.Theresultisthenstoredinthememorylocationdenotedbythefirstvariableandreturned.
Alltheothercombinedoperatorsworkinthesamewaybymakingthearithmeticaloperation
betweenthetwovaluesfirst,thenassigningtheresultofthatoperationtothefirstvariable–tobecomeitsnewstoredvalue.
Withthe%=combinedoperator,thegroupedleft-handoperandaisdividedbythegroupedright-handoperandb,thentheremainderofthatoperationisassignedtotheafirstvariable.
Assign
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Assign”
Typethesestatementstodeclaretwointegervariablesinta;intb;
Next,addstatementstooutputsimpleassignedvaluesConsole.Write(“AssignValues:”);Console.Write(“\ta=”+(a=8));Console.WriteLine(“\tb=”+(b=4));
Now,addstatementstooutputcombinedassignedvaluesConsole.Write(“\n\nAddandAssign:”);Console.Write(“\ta+=b(8+=4)\ta=”+(a+=b));
Console.Write(“\n\nSubtractandAssign:”);Console.Write(“\ta-=b(12-=4)\ta=”+(a-=b));
Console.Write(“\n\nMultiplyandAssign:”);Console.Write(“\ta*=b(8*=4)\ta=”+(a*=b));
Console.Write(“\n\nDivideandAssign:”);Console.Write(“\ta/=b(32/=4)\ta=”+(a/=b));
Console.Write(“\n\nModulusandAssign:”);Console.Write(“\ta%=b(8%=4)\ta=”+(a%=b));Console.ReadKey();
PressStartorF5toruntheapplicationandseetheresultsproducedbyeachassignmentoperator
Noticehow\n\nescapesequencesareusedheretoaddtwonewlinesforspacingoutput.
Theoperandsmustbeofthesamedatatype,ortheright-handoperandmustbeimplicitlyconvertibletothetypeoftheleft-handoperand.
ComparingvaluesTheoperatorsthatarecommonlyusedinC#programmingtocomparetwonumericalvaluesarelistedinthetablebelow:
Operator: Comparativetest:
== Equality
!= Inequality
> Greaterthan
< Lessthan
>= Greaterthanorequalto
<= Lessthanorequalto
Thecomparisonoperatorsarealsoknownas“relationaloperators”.
The==equalityoperatorcomparestwooperandsandwillreturntrueifbothareequalinvalue,otherwisethe==operatorwillreturnfalse.Ifbotharethesamenumber,theyareequal,orifbotharecharacters,theirASCIIcodevaluesarecomparednumerically.
Conversely,the!=inequalityoperatorreturnstrueiftwooperandsarenotequal,usingthesamerulesasthe==equalityoperator,otherwiseitreturnsfalse.Equalityandinequalityoperatorsareusefulintestingthestateoftwovariablestoperformconditionalbranchinginaprogram.
YoucanspecifyaBooleanvaluetotheConvert.ToDouble()methodtodiscoverthattrueisrepresentednumericallyas1,andfalseisrepresentedas0.
The>“greaterthan”operatorcomparestwooperandsandwillreturntrueifthefirstisgreaterinvaluethanthesecond,oritwillreturnfalseifitisequalorlessinvalue.The<“lessthan”operatormakesthesamecomparisonbutreturnstrueifthefirstoperandislessinvaluethanthesecond,otherwiseitreturnsfalse.Typically,a>“greaterthan”or<“lessthan”operatorisusedtotestthevalueofaniterationcounterinaloopstructure.
Addingthe=assignmentoperatoraftera>“greaterthan”operatorora<“lessthan”operatormakesitalsoreturntrueifthetwooperandsareexactlyequalinvalue.
Comparison
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Comparison”
Typethesestatementstodeclarethreeintegervariablesandtwocharactervariablestobecomparedintnil=0,num=0,max=1;charcap=‘A’,low=‘a’;
Next,addstatementstooutputtheresultofequalitycomparisonsofintegersandcharactersConsole.Write(“Equality:”);Console.Write(“\t(0==0):”+(nil==num));Console.Write(“\n\t\t(A==a):”+(cap==low));
Now,addstatementstooutputtheresultofotherintegercomparisonsConsole.Write(“\n\nInequality:”);Console.Write(“\t(0!=1):”+(nil!=max));
Console.Write(“\n\nGreater:”);Console.Write(“\t(0>1):”+(nil>max));
Console.Write(“\nLess:”);Console.Write(“\t\t(0<1):”+(nil<max));
Console.Write(“\n\nGreater/Equal:”);Console.Write(“\t(0>=0):”+(nil>=num));
Console.Write(“\nLessorEqual:”);Console.Write(“\t(1<=0):”+(max<=nil));Console.ReadKey();
PressStartorF5toruntheapplicationandseetheresultsproducedbyeachcomparison
TheASCIIcodevalueforuppercase‘A’is65butforlowercase‘a’it’s97–sotheircomparisonherereturnsfalse.
Whencomparingnumbers,remembertotestforequalityaswellastestingforhigherandlowervalues.
AssessinglogicThelogicaloperatorsmostcommonlyusedinC#programmingarelistedinthetablebelow:
Operator: Operation:
&& Logical-AND
|| Logical-OR
! Logical-NOT
ThelogicaloperatorsareusedwithoperandsthathaveBooleanvaluesoftrueorfalse,orarevaluesthatconverttotrueorfalse.
The&&logical-ANDoperatorwillevaluatetwooperandsandreturntrueonlyifbothoperandsthemselvesaretrue.Otherwise,the&&logical-ANDoperatorwillreturnfalse.Thisisusedinconditionalbranchingwherethedirectionofaprogramisdeterminedbytestingtwoconditions–ifbothconditionsaresatisfied,theprogramwillgoinacertaindirection,otherwiseitwilltakeadifferentdirection.
Theterm“Boolean”referstoasystemoflogicalthoughtdevelopedbytheEnglishmathematicianGeorgeBoole(1815-1864).
Unlikethe&&logical-ANDoperator,whichneedsbothoperandstobetrue,the||logical-ORoperatorwillevaluateitstwooperandsandreturntrueifeitheroneoftheoperandsitselfreturnstrue.If,however,neitheroperandreturnstrue,thenthe||logical-ORoperatorwillreturnfalse.ThisisusefulinC#programmingtoperformacertainactionifeitheroneoftwotestconditionshasbeenmet.
The!logical-NOToperatorisaunaryoperatorthatisusedbeforeasingleoperand.Itreturnsthe
inversevalueofthegivenoperand,soifthevariableahadavalueoftruethen!awouldhaveavalueoffalse.The!logical-NOToperatorisusefulinC#programstotogglethevalueofavariableinsuccessiveloopiterationswithastatementlikea=!a.Thisensuresthatoneachpassthevalueischanged,likeflickingalightswitchonandoff.
Logic
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Logic”
TypethisstatementtodeclaretwoBooleanvariablesboolyes=true,no=false;
AddthesestatementstooutputtheresultofANDlogicConsole.Write(“ANDLogic:”);Console.Write(“\t(yes&&yes):”+(yes&&yes));Console.Write(“\n\t\t(yes&&no):”+(yes&&no));Console.Write(“\n\t\t(no&&no):”+(no&&no));
Now,addstatementstooutputtheresultofORlogicConsole.Write(“\n\nORLogic:”);Console.Write(“\t(yes||yes):”+(yes||yes));Console.Write(“\n\t\t(yes||no):”+(yes||no));Console.Write(“\n\t\t(no||no):”+(no||no));
Then,addstatementstooutputtheresultofNOTlogicConsole.Write(“\n\nNOTLogic:”);Console.Write(“\tyes=”+yes);Console.Write(“\t!yes=”+!yes);Console.Write(“\n\t\tno=”+no);Console.Write(“\t!no=”+!no);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheresultsproducedbyeachlogicaloperation
Thevaluereturnedbythe!logical-NOToperatoristheinverseofthestoredvalue–thestoredvalueitselfremainsunchanged.
Noticethatfalse&&falsereturnsfalse,nottrue–demonstratingthemaxim“twowrongsdon’tmakearight”.
ExaminingconditionsPossiblytheC#programmer’smostfavoritetestoperatoristhe?:“ternary”operator.Thisoperatorfirstevaluatesanexpressionforatrueorfalsecondition,thenreturnsoneoftwospecifiedvaluesdependingontheresultoftheevaluation.Forthisreasonitisalsoknownasthe“conditional”operator.
The?:ternaryoperatorhasthissyntax:
(test-expression)?if-true-return-this:if-false-return-this;
Althoughtheternaryoperatorcaninitiallyappearalittleconfusing,itiswellworthbecomingfamiliarwiththisoperatorasitcanexecutepowerfulprogrambranchingwithminimalcode.Forexample,tobranchwhenavariableisnotavalueofone:
(variable!=1)?if-true-do-this:if-false-do-this;
Theternaryoperatorhasthreeoperands–theonebeforethe?andthosebeforeandafterthe:.
TheternaryoperatoriscommonlyusedinC#programmingtoassignthemaximumorminimumvalueoftwovariablestoathirdvariable.Forexample,toassignaminimumlikethis:
c=(a<b)?a:b;
Theexpressioninparenthesesreturnstruewhenthevalueofvariableaislessthanthatofvariableb–sointhiscase,thelesservalueofvariableagetsassignedtovariablec.
Similarly,replacingthe<lessthanoperatorinthetestexpressionwiththe>greaterthanoperatorwouldassignthegreatervalueofvariablebtovariablec.
Anothercommonuseoftheternaryoperatorincorporatesthe%modulusoperatorinthetestexpressiontodeterminewhethertheparityvalueofavariableisanoddnumberoranevennumber:
(variable%2!=0)?if-true(odd)-do-this:if-false(even)-do-this;
Wheretheresultofdividingthevariablevaluebytwodoesleavearemainder,thenumberisodd–wherethereisnoremainder,thenumberiseven.Thetestexpression(variable%2==1)wouldhavethesameeffect,butitispreferabletotestforinequality–it’seasiertospotwhensomethingisdifferentthanwhenit’sidentical.
Valueequality,wheretwovariablescontainanequalvalue,isalsoknownas“equivalence”.
Condition
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Condition”
Typethisstatementtodeclareandinitializetwointegervariablesinta=8;intb=3;
Next,addthesestatementstooutputanappropriatestringwithcorrectgrammarforquantitystringverb=(a!=1)?“are“:“is“;Console.Write(“There”+verb+a+”\n”);
Now,addstatementstooutputanappropriatestringcorrectlydescribingtheparityofeachvariablevaluestringparity=(a%2!=0)?“Odd“:“Even“;Console.Write(a+“is“+parity);
parity=(b%2!=0)?“Odd“:“Even“;Console.Write(b+“is“+parity);
Then,addstatementstooutputastringreportingthegreaterofthesetwovariablevaluesintmax=(a>b)?a:b;Console.Write(“\nMaximumis“+max);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheresultsproducedbyexaminingeachvariablevalue
The?:ternaryoperatorcanreturnvaluesofanydatatype–numbers,strings,Booleans,etc.
SettingprecedenceOperatorprecedencedeterminestheorderinwhichC#evaluatesexpressions.Forexample,theexpression1+5*3evaluatesto16,not18,becausethe*multiplicationoperatorhasahigherprecedencethanthe+additionoperator.Parenthesescanbeusedtospecifyprecedence,sothat(1+5)*3evaluatesto18.
The*multiplyoperatorisonahigherrowthanthe+additionoperator–sointheexpressiona=1+5*3,multiplicationiscompletedfirst,beforetheaddition.
Whenoperatorshaveequalprecedence,their“associativity”determineshowexpressionsaregrouped.Forexample,the-subtractionoperatorisleft-associative,groupingleft-to-right(LTR),so8-4-2isgroupedas(8-4)-2andthusevaluatesto2.Otheroperatorsareright-associative,groupingright-to-left(RTL).
Thetablebelowlistscommonoperatorsinorderofprecedence,withthehighest-precedenceonesatthetop.Operatorsonthesamelinehaveequalprecedence,sooperatorassociativitydetermineshowexpressionsaregroupedandevaluated.
Category: Operator: Associativity:
Postfix ()[].++-- LTR
UnarySignPrefix
!+-++--
RTL
Multiplicative */% LTR
Additive +- LTR
Comparative <<=>>= LTR
Equivalence ==!= LTR
Conditional && LTR
Conditional || LTR
Conditional ?: RTL
Assignment =+=-=*=/=%= RTL
Comma , LTR
Therearealsoanumberof“bitwise”operators,whichareusedtoperformbinaryarithmetic.ThisisoutsidethescopeofthisbookbutthereisasectiondevotedtobinaryarithmeticinourbookCProgrammingineasysteps.ThoseoperatorsperforminjustthesamewayinC#.
Precedence
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Precedence”
Typethisstatementtodeclareanintegervariableintsum;
Addthesestatementstoinitializethevariablewiththeresultofanungroupedexpressionanddisplaythatresultsum=1+4*3;Console.Write(“DefaultOrder:\t\t”+sum);
Next,addstatementstoassigntheresultofagroupedexpressionanddisplaythatresultsum=(1+4)*3;Console.Write(“ForcedOrder:\t\t”+sum);
Addstatementstoassigntheresultofanewungroupedexpressionanddisplaythatresultsum=7-4+2;Console.Write(“\nDefaultDirection:\t”+sum);
Now,addstatementstoassigntheresultofthenewgroupedexpressionanddisplaythatresultsum=7-(4+2);Console.Write(“\nForcedDirection:\t”+sum);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheresultsproducedbyexaminingeachvariablevalue
The*multiplicationoperatortakesprecedenceoverthe+additionoperator–somultiplicationisperformedfirst.
The-subtractionoperatorandthe+additionoperatorhaveequalprecedencebutalsohaveleft-to-rightassociativity–sosubtractionisperformedfirstbeforeaddition.
Itisbesttoclarifyallexpressionsbyaddingparenthesestogroupoperations.
Summary• Arithmeticoperatorscanformexpressionswithtwooperandsfor+addition,-subtraction,*
multiplication,and/division.
• The%modulusarithmeticoperatordividesthefirstoperandbyitssecondoperand,thenreturnstheremainder.
• Caremustbetakentogroupexpressionswithin()parentheseswheremorethanoneoperatorisused.
• The++incrementand--decrementoperatorsmaybepostfixedorprefixedtomodifyasingleoperandbyone.
• The=assignmentoperatorcanbecombinedwithanarithmeticoperatortoassigntheresultofanoperation.
• Comparisonoperatorscanformexpressionswithtwooperandsfor==equalityorfor!=inequality.
• Comparisonoperatorscanformexpressionswithtwooperandsfor>greaterorfor<lesservaluecomparison.
• Equalitycanalsoberecognizedincomparisonswiththe>=greater-or-equaland<=less-or-equaloperators.
• The&&logical-ANDoperatorevaluatestwooperandsandwillreturntrueonlyifbothoperandsarethemselvestrue.
• The||logical-ORoperatorevaluatestwooperandsandwillreturntrueifeitherofthetwooperandsarethemselvestrue.
• The!logical-NOToperatorreturnstheinverseBooleanvalueofasinglegivenoperand.
• The?:ternaryoperatorevaluatesagivenBooleanexpression,thenreturnsoneoftwooperandsdependingontheresult.
• Operatorprecedencedeterminestheorderinwhichexpressionsareevaluated.
• Whenoperatorshaveequalprecedence,theirassociativitydetermineshowexpressionsaregroupedforevaluation.
4
Makingstatements
ThischapterdemonstrateshowstatementscanevaluateexpressionstodeterminethedirectioninwhichaC#programwill
proceed.
BranchingwithifSwitchingbranchesLoopingforLoopingwhileIteratingforeachSummary
BranchingwithifTheC#ifkeywordperformsthebasicconditionaltestthatevaluatesagivenexpressionforaBooleanvalueoftrueorfalse–anditssyntaxlookslikethis:
if(test-expression){statements-to-execute-when-true}
Thebracesfollowingthetestmaycontainoneormorestatements,eachterminatedbya;semicolon,butthesewillonlybeexecutedwhentheexpressionisfoundtobetrue.Whenthetestisfoundtobefalse,theprogramproceedstoitsnexttask.
Toallow“conditionalbranching”,anifstatementcanofferalternativestatementstoexecutewhenthetestfailsbyappendinganelsestatementblockaftertheifstatementblock,likethis:
if(test-expression){statements-to-execute-when-true}else{statements-to-execute-when-false}
Totesttwoconditions,thetestexpressionmayusethe&&operator.Forexample,if((num>5)&&(letter==‘A’)).
ShorthandcanbeusedwhentestingaBooleanvalue–sotheexpressionif(flag==true)canbewrittenasif(flag).
Alternatively,anifstatementcanbe“nested”withinanotherifstatement,sothosestatementsintheinnerstatementblockwillonlybeexecutedwhenbothtestssucceed–butstatementsintheouterstatementblockwillbeexecutediftheoutertestsucceeds:
IfElse
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“IfElse”
TypethesestatementstocreateandinitializetwovariablesfromuserinputConsole.Write(“PleaseEnterANumber:”);doublenum=Convert.ToDouble(Console.ReadLine());Console.Write(“Thanks.NowEnterALetter:”);charletter=Convert.ToChar(Console.ReadLine());
Next,addastatementtooutputamessageiftheuser’snumberinputexceedsaspecifiedvalueif(num>=6){Console.WriteLine(“\nNumberExceeds5”);//Nestedstatementtobeinsertedhere(Step5).
}
Avoidnestingmorethanthreelevelsofifstatements–topreventconfusionanderrors.
Now,addastatementtooutputanalternativemessageiftheuser’snumberinputislessthanthespecifiedvalueelse{Console.WriteLine(“\nNumberIs5OrLess”);
}Console.ReadKey();
Insertastatementwithintheifblocktooutputamessagewhentheuser’sletterinputmatchesaspecifiedvalueif(letter==‘C’){Console.WriteLine(“LetterIs‘C’”);
}
PressStartorF5toruntheapplicationandentervaluestoseetheprogrambranchaccordingtoyourinput
Wherethereisonlyonestatementtoexecute,whenthetestsucceedsthe{}bracesmaybeomitted–butretainingthemaidscodeclarity.
SwitchingbranchesTheifandelsekeywords,introducedabove,allowprogramstobranchinaparticulardirectionaccordingtotheresultofatestcondition,andcanbeusedtorepeatedlytestavariabletomatchavalue.Forexample,testingforaninteger:
if(num==1){Console.Write(“Monday”);}elseif(num==2){Console.Write(“Tuesday”);}elseif(num==3){Console.Write(“Wednesday”);}elseif(num==4){Console.Write(“Thursday”);}elseif(num==5){Console.Write(“Friday”);}
Theprogramwillbranchinthedirectionofthematch.
Avoidwritinglengthyif-elsestatementsliketheoneshownhere–wherepossible,useaswitchstatementinstead.
Conditionalbranchingwithlongif-elsestatementscanoftenbemoreefficientlyperformedusingaswitchstatementinstead,especiallywhenthetestexpressionevaluatesjustonevariable.
Theswitchstatementworksinanunusualway.Ittakesagivenvariablevalue,orexpression,thenseeksamatchingvalueamonganumberofcasestatements.Statementsassociatedwiththematchingcasestatementbya:colonwillthenbeexecuted.
Whennomatchisfound,nocasestatementswillbeexecuted,butyoumayaddadefaultstatementafterthefinalcasestatementtospecifystatementstobeexecutedwhennomatchisfound.Thesyntaxofatypicalswitchstatementlookslikethis:
switch(variable-name){casevalue1:statement;break;casevalue2:statement;break;casevalue3:statement;break;default:statement;
}
Itisimportanttofolloweachcasestatementwiththebreakkeyword.Unlikeotherprogramminglanguages,C#doesnotallowfall-throughfromonecasestatementtoanother–eachcasestatementmustallowcontroltobehandedbackinordertoexittheswitchblock.
MissingbreakkeywordsinC#casestatementsaresyntaxerrors.
Switch
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Switch”
Typethisstatementtocreateandinitializeanintegervariableintnum=3;
Next,addastatementtodeclareastringvariablestringday;
Now,addastatementtoinitializethestringvariableaccordingtothevalueoftheintegervariableswitch(num){case1:day=“Monday”;break;case2:day=“Tuesday”;break;case3:day=“Wednesday”;break;case4:day=“Thursday”;break;case5:day=“Friday”;break;//Defaultstatementtobeinsertedhere(Step5).
}
Then,insertafinalstatementintotheswitchblocktoinitializethestringvariablewhennomatchisfounddefault:day=“WeekendDay”;
Finally,addstatementstooutputtheassignedvalueConsole.WriteLine(“Day”+num+“:“+day);Console.ReadKey();
PressStartorF5toruntheapplicationandseethestringresultoftheswitchblockassignment
Acasestatementcanalsotrytomatchagainstastringvalue.Forexample:case:“ABC”.
Thedefaultstatementdoesnotneedtobefollowedbyabreakkeyword–becauseadefaultstatementalwaysappearsattheendofaswitchblock.
LoopingforAloopisapieceofcodeinaprogramthatautomaticallyrepeats.Onecompleteexecutionofallstatementscontainedwithintheloopblockisknownasan“iteration”or“pass”.
Thenumberofiterationsmadebyaloopiscontrolledbyaconditionaltestmadewithintheloop.Whilethetestedexpressionremainstrue,theloopwillcontinue–untilthetestedexpressionbecomesfalse,atwhichtimetheloopends.
ThethreetypesofloopstructuresinC#programmingareforloops,whileloops,anddo-whileloops.Perhapsthemostcommonlyusedloopistheforloop,whichhasthissyntax:
for(initializer;test-expression;updater){statements}
Theinitializersetsthestartingvalueforacounterofthenumberofiterationstobemadebytheloop.Anintegervariableisusedforthispurposeandistraditionallynamed“i”.
Uponeachiterationoftheloop,thetestexpressionisevaluatedandthatiterationwillonlycontinuewhilethisexpressionistrue.Whenthetestedexpressionbecomesfalse,theloopendsimmediatelywithoutexecutingthestatementsagain.Oneachiterationthecounterisupdatedthenthestatementsexecuted.
Loopsmaybenestedwithinotherloops–sothattheinnerloopwillfullyexecuteitsiterationsoneachiterationoftheouterloop.
Theupdatermayincrementthecounterusingthe++operatortocountup,ordecrementthecounterusingthe--decrementoperatortocountdown.
ForLoop
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“ForLoop”
Typethesestatementstocreatealoopthatwillmakethreeiterationsfor(inti=1;i<4;i++){Console.WriteLine(“LoopIteration:“+i);//Nestedlooptobeinsertedhere(Step4).
}Console.ReadKey();
PressStartorF5toruntheapplicationandseetheloopcounterdisplayedoneachiteration
Insidetheforloopblock,insertanotherforloopthatwillalsomakethreeiterationsfor(intj=1;j<4;j++){Console.WriteLine(“\tInnerLoopIteration:“+j);
}
PressStartorF5toruntheapplicationoncemoreandnowseebothloopcountersdisplayedoneachiteration
Onthethirditerationoftheseloops,theupdaterincrementsthecountervalueto4–sowhenitisnextevaluatedthetestexpressionreturnsfalseandtheloopends.
LoopingwhileAnalternativetotheforloop,introducedhere,usesthewhilekeyword,followedbyanexpressiontobeevaluated.Whentheexpressionistrue,statementscontainedwithinbracesfollowingthetestexpressionwillbeexecuted.Theexpressionwillthenbeevaluatedagainandthewhileloopwillcontinueuntiltheexpressionisfoundtobefalse.
while(test-expression){statements}
Theloop’sstatementblockmustcontaincodethatwillaffectthetestedexpressioninordertochangetheevaluationresulttofalse,otherwiseaninfiniteloopiscreatedthatwilllockthesystem!Whenthetestedexpressionisfoundtobefalseuponitsfirstevaluation,thewhileloop’sstatementblockwillneverbeexecuted.
Asubtlevariationofthewhileloopplacesthedokeywordbeforetheloop’sstatementblockandawhiletestafterit,withthissyntax:
do{statements}while(test-expression);
Inado-whileloopthestatementblockwillalwaysbeexecutedatleastonce–becausetheexpressionisnotevaluateduntilafterthefirstiterationoftheloop.
Ifyouaccidentallystartrunninganinfiniteloop,forexample:while(true){Console.Write(i);i++;
}pressCtrl+Ckeystoterminatetheprocess.
BreakingoutofloopsAbreakstatementcanbeincludedinanykindoflooptoimmediatelyterminatetheloopwhenatestconditionismet.Thebreakensuresnofurtheriterationsofthatloopwillbeexecuted.
Similarly,acontinuestatementcanbeincludedinanykindoflooptoimmediatelyterminatethatparticulariterationoftheloopwhenatestconditionismet.Thecontinuestatementallowsthelooptoproceedtothenextiteration:
WhileLoop
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“WhileLoop”
Typethesestatementstocreateandinitializeanintegerarrayvariableandaregularintegercountervariableint[]nums=newint[10];inti=0;
Next,addawhilelooptoassignitsincrementingcountervaluetoanarrayelementanddisplayitoneachiterationwhile(i<nums.Length){nums[i]=i;Console.Write(“|“+nums[i]);i++;
}Console.Write(“\n\n“);
Noticehowthearray’sLengthpropertyisusedtodeterminethenumberofelementsitcontains.
Now,addado-whilelooptodisplayitsdecrementingcountervalueoneachiterationdo{i--;//Statementstobeinsertedhere(Step6).Console.Write(“|“+nums[i]);
}while(i>0);Console.ReadKey();
Rememberthatthewhilestatementattheendofado-whileloopmustbeterminatedwitha;semicolon.
PressStartorF5toruntheapplicationandseebothloopcountersdisplayedoneachiteration
Inthedo-whileloop,insertastatementtoskipasingleiteration,andastatementtoprematurelyexittheloopif(i==8){Console.Write(“|Skipped”);continue;}if(i==3){Console.Write(“|Done”);break;}
PressStartorF5toruntheapplicationoncemore,andnowseethedo-whileloopiterationsskipped
Thepositionofbreakandcontinuestatementsisimportant–theymustappearaftertheupdater,toavoidcreatinganinfiniteloop,butbeforeanyotherstatements,topreventtheirexecution.
IteratingforeachC#providesaspecialforeach-instatementthatallowsyoutoeasilytraverseallelementsinanarraytoaccessallstoredvalues.Thisisan“iterator”,ratherthanaloopstructure,soitcannotbeusedtoassignormodifyelementvalues–itcanonlybeusedtoreadtheirvalues.Syntaxofaforeach-instatementlookslikethis:
foreach(data-typevariable-nameinarray-name){statements}
Useaforloopifyouneedtoassignormodifyelementvalues.
Theforeachkeywordmustspecifyavariableofanappropriatedatatypetowhicheachelementvaluecanbeassigned,onebyone,andtheinkeywordmustspecifythenameofthearray:
ForEach
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“ForEach”
Typethisstatementtocreateandinitializeastringarraystring[]websites=newstring[5]{“Google”,“YouTube”,“Facebook”,“Baidu”,“Yahoo!”};
Next,addastatementtodisplayalistheadingConsole.WriteLine(“PopularWebsites...“);
Now,addaforeachstatementtodisplayacountervalueandelementvalueoneachiterationintrank=1;foreach(stringsiteinwebsites){Console.WriteLine(“Position:“+rank+”\t”+site);rank++;
}Console.ReadKey();
PressStartorF5toruntheapplicationandseetheiteratordisplaythecounterandelementvalues
Thebreakandcontinuekeywordscanbeusedinaforeachstatementtoexittheiterationcycle.
Aforeach-instatementcanalsobeusedtotraverseallelementsofaC#“dictionary”thatcontainsassociatedkey-valuepairs.Thedatatypesofthekeyandvaluemustbespecifiedasacomma-separatedpairwithin<>angledbracketsinthedeclaration:
Dictionary<data-type,data-type>dictionary-name=newDictionary<data-type,data-type>();
TheforeachkeywordmustspecifyaKeyValuePairtowhicheachkey-valuepairvaluecanbeassigned,onebyone,andtheinkeywordmustspecifythenameofthedictionary:
KeyValue
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“KeyValue”
Typethesestatementstocreateandinitializeadictionarynamed“BookList”Dictionary<string,string>BookList=
newDictionary<string,string>();BookList.Add(“StuartYarnold”,“Arduino”);BookList.Add(“NickVandome”,“Windows10”);BookList.Add(“MikeMcGrath”,“Java”);
Now,addastatementtodisplayalistheadingConsole.WriteLine(“PopularTitles...“);
Addaforeachstatementtodisplayeachkey-valuepairforeach(KeyValuePair<string,string>bookinBookList){Console.WriteLine(“Key:“+book.Key+
“\tValue:”+book.Value+“ineasysteps”);}Console.ReadKey();
PressStartorF5toruntheapplicationandseetheiteratordisplaythedictionary’skey-
valuepairs
NotethataDictionaryobjecthasAdd()andRemove()methods,andhasKeyandValueproperties.
TheDictionaryclassispartoftheSystem.Collections.Genericlibrary–sothismustbeincludedintheprogramusingstatements.
Summary• AnifstatementevaluatesagiventestexpressionforaBooleanvalueoftrueorfalse.
• Statementscontainedinbracesafteranifstatementwillonlybeexecutedwhentheevaluationisfoundtobetrue.
• Multipleifstatementscanbenested,sostatementsintheinnerloopareonlyexecutedwhenbothlooptestsreturntrue.
• Theifandelsekeywordsareusedtoperformconditionalbranchingaccordingtotheresultofatestedexpression.
• Aswitchstatementisanalternativeformofconditionalbranchingthatmatchesacasestatementtoagivenvalue.
• Eachcasestatementmustbeterminatedbythebreakkeyword,asC#doesnotallowfall-through.
• Theforloopstructurehasparametersdeclaringaninitializer,atestexpression,andanupdater.
• Aloopupdatermay++incrementacountertocountup,ormay--decrementacountertocountdown.
• Awhileloopmayneverexecuteitsstatements,butado-whileloopwillalwaysexecuteitsstatementsatleastonce.
• Awhileloopanddo-whileloopmustalwayshaveanupdaterwithintheirloopbodytoavoidcreatinganinfiniteloop.
• Anytypeofloopcanbeimmediatelyterminatedbyincludingabreakstatementwithintheloopbody.
• Asingleiterationofanytypeofloopcanbeskippedbyincludingacontinuestatementwithintheloopbody.
• Aforeach-instatementisaniteratorthatcantraverseallelementsofanarraytoreadtheirvalues.
• Aforeach-instatementcantraverseallkey-valuepairsofadictionarytoreadtheirvalues.
5
Devisingmethods
ThischapterdemonstrateshowtocreatemethodsthatcanbecalledtoexecutestatementswhenevertheC#program
requiresthem.
CreatingfunctionPassingargumentsOverloadingmethodsRefactoringcodeSummary
CreatingfunctionC#programmer-specifiedmethodsencloseasectionofcodethatprovidesparticularfunctionalitytotheprogram.WhenamethodiscalledfromwithinthedefaultMain()programmethod,itsstatementsareexecutedand,optionally,avaluecanbereturnedtothemainprogramuponcompletion.Wrappingfunctionalityinmodularmethodsprovidesthesethreemainbenefits:
• Modularprogramcodeiseasiertounderstandandmaintain
• Triedandtestedmethodscanbere-usedbyotherprograms
• Theworkloadonlargeprogramscanbemoreeasilyshared
AmethodisdeclaredinaC#programbyspecifyingthevariouselementsofitsstructurewiththissyntax:
access-specifierreturn-data-typemethod-name(parameters){statements
}
Thefirstpartofamethoddeclaration,definingitsaccess,returntype,name,andparameters,isknownasthemethod“signature”.
Theaccessspecifierdeterminesthevisibilityofthemethodtootherclasses,usingkeywordssuchaspublicandprivate.Alternatively,ifthemethodisnotintendedforusebyotherclasses,itcanbeinitializedinmemoryusingthestatickeyword.
Ifthemethodwillreturnavaluetothecaller,thedatatypeofthatvaluemustbespecified.If,ontheotherhand,themethodwillneverreturnavalue,thevoidkeywordmustbespecified.
TheuseofmethodsbyotherclassesisdescribedanddemonstratedinthechapteronObjectOrientedProgramming–seehere.
Anamemustbespecifiedforeachprogrammer-definedmethod,adheringtothesamenamingconventionsasvariablenames.
Optionally,parametersmaybespecifiedwithinparenthesesafterthemethodnametorepresentargumentvaluespassedintothemethodbythecaller.Oncedefined,amethodwithoutparametersmaybecalledsimplybystatingitsnamefollowedbyparentheses.
Variablesdeclaredwithinamethodarenot,bydefault,visibletootherpartsoftheprogram–theyareonlyavailabletocodewithinthatmethodbody.Thevisibilityofvariablesisknownas“variablescope”andvariableswithinmethodshaveonly“local”scope.Thismeansthatvariablesdeclaredindifferentmethodsmaybegiventhesamenamewithoutconflict.
Parametersandargumentsaredemonstratedintheexamplehere.
Method
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Method”
AftertheMain()method,addthismethoddefinitionwithinthe{}bracesoftheclassProgramstaticvoidbodyTempC(){Console.WriteLine(“BodyTemperature...”);Console.WriteLine(“Centigrade:\t37ºC”);
}
YoucanusetheWindowsAccessories,CharacterMapfacilitytoproducethedegree
symbol.
Next,addamethoddefinitionthatreturnsafloating-pointvaluetothecallerstaticdoublebodyTempF(){doubletemperature=98.6;returntemperature;
}
Eachvariablecansharethesamenameastheyhaveonlylocalscope.
Now,addamethoddefinitionthatreturnsanintegervaluetothecallerstaticintbodyTempK(){inttemperature=310;returntemperature;
}
Finally,addstatementswithintheMain()methodtocalleachoftheprogrammer-specifiedmethodsabovebodyTempC();Console.WriteLine(“Fahrenheit:\t”+bodyTempF()+“ºF”);Console.WriteLine(“Kelvin:\t”+bodyTempK()+“K”);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfeaturingthemethodcalls
PassingargumentsMethodsmayoptionallyspecifyoneormoreparametersasacomma-separatedlistwithintheparenthesesoftheirdefinition.Eachspecifiedparametermuststatethedatatypeitmaycontain,andanamebywhichitmaybereferencedwithinthemethod.Forexample,parametersfortextandanumber,likethis:
staticvoidsetUser(stringname,intage){statements}
Whenamethodwithparametersiscalled,thecallermustnormallypassthecorrectnumberofargumentvaluesoftherequireddatatype.Thesearelistedwithintheparenthesesofthecallingstatement.Forexample,callingthemethoddefinedabove:
setUser(“Alison”,18);
Callingamethodwithoutpassingrequiredarguments,orargumentsofthewrongdatatype,willcauseanerror.
Optionally,theparameterdeclarationmaybeassignedadefaultvaluetouseifnoargumentvalueispassedbythecaller.Inthiscase,thecallermaypassoromitanargumentvalue:
staticvoidsetUser(stringname,intage=21){statements}
setUser(“Brenda”,19);setUser(“Christine”); //Agewillbe21.
Therearethreewaystopassargumentsintomethods:
• ByValue–argumentspassedtomethods“byvalue”assignacopyoftheoriginalvaluetotheparameter.Changesmadetotheparameterinsidethemethoddonotaffecttheoriginalvalue.
• ByReference–argumentspassedtomethods“byreference”assigntheaddressofthememorylocationoftheoriginalvaluetotheparameter.Changesmadetotheparameterinsidethemethoddoaffecttheoriginalvalue.ReferenceargumentsmustincludetheC#refkeywordinboththemethodcallparenthesesandthemethoddefinitionparameterlist.
• ForOutput–argumentspassedtomethods“foroutput”assigntheaddressofthememorylocationoftheargumenttotheparameter,towhichthemethodcanassignavalue.Thisissimilartopassinganargumentbyreferenceexceptthatdataispassedfromthemethod,ratherthantothemethod.OutputargumentsmustincludetheC#outkeywordinboththemethodcallparenthesesandthemethoddefinitionparameterlist.Thisisusefultoreturnmorethanonevaluefromamethod.
Mostmethodcallspassargumentsbyvalueratherthanbyreferenceorforoutput.
Parameter
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Parameter”
Typethesestatementstodeclaretwovariablesdoubleweight;stringnum;
AftertheMain()method,addthismethoddefinitiontooutputadoublevalueandtoreturnastringvaluestaticstringgetWeight(outdoubletheWeight){theWeight=10;return“Ten”;
}
Next,addamethoddefinitionthatreturnsamultipliedvalueofitsparameterargumentstaticdoublelbToKg(doublepounds=5){return(pounds*0.45359237);}
Thedefaultparametervalueisnotusedhereasthecallerpassesinanargumentvalue.
Now,addamethoddefinitionthatassignsadividedvaluetoitsparameterreferenceargumentstaticvoidkgToLb(refdoubleweight){weight=(weight/0.45359237);}
Finally,addstatementswithintheMain()methodtopassargumentstoeachofthemethodsdeclaredabovenum=getWeight(outweight);Console.WriteLine(num+“lb=”+lbToKg(weight)+“kg”);kgToLb(refweight);Console.WriteLine(num+“kg=”+weight+“lb”);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfeaturingargumentspassedtomethodparameters
BoththenumandweightvariablesareinitializedbythegetWeight()method.Areferencetotheweightvariableispassedlatertoassignitanewvalue.
OverloadingmethodsMethod“overloading”allowsmethodsofthesamenametohappilyco-existinthesameprogram,providingtheirparametersdifferinnumber,datatype,orbothnumberanddatatype.Thecompilermatchesamethodcalltothecorrectversionofthemethodbyrecognizingitsparameternumberanddatatypes–aprocessknownas“methodresolution”.Therearesomepointstoconsiderwhencreatingoverloadedmethods:
• Whereaparameterrepresentsthesamevalueasthatinanothermethod,theparametersshouldhavethesamename.
• Parameterswiththesamenameshouldappearinthesamepositionineachmethod’sparameterlist.
• Youshouldnotusereforoutmodifierstooverloadmethods.
Itisusefultocreateoverloadedmethodswhenthetaskstheyaretoperformaresimilar,yetsubtlydifferent.
Overload
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Overload”
AftertheMain()method,addthismethoddefinitiontoreturnthecalculatedareaofacirclestaticdoublecomputeArea(doublewidth){doubleradius=width/2;return((radius*radius)*3.141593);
}
Next,addamethoddefinitiontoreturnthecalculatedareaofasquarestaticdoublecomputeArea(doublewidth,doubleheight){return(width*height);
}
Then,addamethoddefinitiontoreturnthecalculatedareaofatrianglestaticdoublecomputeArea(doublewidth,doubleheight,charletter){return((width/2)*height);
}
Methoddefinitionsthatonlydifferbytheirreturndatatypecannotbeoverloaded–it’stheparametersthatmustdiffer.Methodresolutiondoesnottakereturndatatypesintoconsideration.
Now,turnyourattentiontotheMain()methodandbeginbydeclaringtwofloating-pointvariablesdoublenum;doublearea;
Next,addstatementstoinitializethefirstvariablefromuserinputConsole.Write(“PleaseEnterDimensionInFeet:“);num=Convert.ToDouble(Console.ReadLine());
RememberthattheReadLine()methodreturnsastringvalue–sothismustbeconvertedinordertoperformarithmetic.
Now,initializethesecondvariablebycallingthemethodthatacceptsonlyoneargumentanddisplayitsvaluearea=computeArea(num);Console.WriteLine(“\nCircle:\t\tArea=“+area+“sq.ft.”);
Assignanewvaluetothesecondvariablebycallingthemethodthatacceptstwoargumentsanddisplayitsvaluearea=computeArea(num,num);Console.WriteLine(“Square:\t\tArea=“+area+“sq.ft.”);
Assignanothervaluetothesecondvariablebycallingthemethodthatacceptsthreeargumentsanddisplayitsvaluearea=computeArea(num,num,‘T’);Console.WriteLine(“Triangle:\tArea=“+area+“sq.ft.”);Console.ReadKey();
PressStartorF5toruntheapplication,thenenteranumberandseetheoutputfromtheoverloadedmethods
Thevaluepassedtothecharletterparameterisneverusedhere–itisincludedmerelytodeterminewhichmethodshouldbecalled.
RefactoringcodeMethodscancallthemselvesrecursively,torepeatedlyexecutethestatementscontainedintheirmethodbody–muchlikealoop.Aswithloops,arecursivemethodmustcontainanupdater,andaconditionaltesttocallitselfagainorstoprepeatingwhenaconditionismet.Thesyntaxofarecursivemethodlookslikethis:
return-data-typemethod-name(parameter-list){
statements-to-be-executed;updater;conditional-test-to-recall-or-exit;
}
Theupdaterwillchangethevalueofapassedargument–sosubsequentcallswillpasstheadjustedvaluebacktothemethod:
Refactor
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Refactor”
AftertheMain()method,addthisrecursivemethodtoreturnthefactorialvalueofanintegerargumentstaticintfactorial(intnum){intresult;if(num==1){result=1;
}else{result=(factorial(num-1)*num);
}returnresult;
}
Next,addamethodtodisplayarangeofintegersandtheircomputedfactorialvaluesstaticvoidcomputeFactorials(intnum,intmax){while(num<=max){Console.Write(“FactorialOf“+num+“:“);Console.WriteLine(factorial(num));num++;
}}
ThetwocallstowriteoutputinStep3couldberefactoredintoasingleWriteLine()callforgreaterefficiency.
Now,addstatementswithintheMain()methodtopassarangeofargumentvaluestobecomputedfordisplaycomputeFactorials(1,8);Console.ReadKey();
PressStartorF5toruntheapplicationtoseetheoutput
IfyouaccidentallyrunaninfiniterecursivefunctionpresstheCtrl+Ckeystoterminatetheprocess.
Theoutputlistsfactorialvalues(factorial3is3x2x1=6,etc.)buttheprogramcanbeoptimizedbyrefactoringtherecursivefactorial()method.Thismethoddoesnotneedavariableifwrittenwiththeternaryoperator:
Editthefactorial()method,listedinStep2,tomakeitmoreefficientstaticintfactorial(intnum){return(num==1)?1:(factorial(num-1)*num);
}
PressStartorF5toruntheapplicationoncemoreandseethesameoutput,producedmoreefficiently
Arecursivemethodgenerallyusesmoresystemresourcesthanaloop–butitcanmakethecodemorereadable.
Summary• Aprogrammer-specifiedmethodisamodularsectionofcodethatcanbecalledtoexecuteits
statementswheneverrequired.
• Itiseasiertounderstand,maintain,re-use,andsharemodularprogramcodethatcontainsmethods.
• Amethoddeclarationmustatleastspecifyareturndatatypeandthemethodname.
• Methodsnotintendedforusebyotherclassesmustbeinitializedinmemorybythestatickeyword.
• Optionally,amethoddeclarationmayincludeaparameterlist.
• Variablesdeclaredwithinamethodhavelocalscopebydefault,soarenotaccessiblefromoutsidethatmethod.
• Argumentspassedbyvalueassignacopyoftheoriginalvaluetothemethodparameter,sotheoriginalwillnotbeaffected.
• Argumentspassedbyreferenceassignamemorylocationtothemethodparameter,sotheoriginalvaluewillbeaffected.
• Argumentspassedforoutputretrieveavaluefromthemethodandareusefultoreturnmorethanonevalue.
• Methodoverloadingallowsmethodsofthesamenametoco-existinthesameprogramiftheirparametersdiffer.
• Thecompilermatchescallstooverloadedmethodsbyrecognizingtheirparameternumberanddatatypes.
• Parametersrepresentingthesamevaluesinoverloadedmethodsshouldhavethesamenameandthesameposition.
• Thereferencerefandoutputoutmodifiersshouldnotbeusedwithoverloadedmethods.
• Codecanberefactoredforoptimumefficiencybyreducingthenumberofvariablesandmethodcalls.
• Recursivemethodsrepeatedlyexecutetheirstatements,somustcontainanupdatertostoprepeatingatsomepoint.
6
Handlingstrings
ThischapterdemonstrateshowtomanipulateandformattextstringswithinC#programs.
DiscoveringstringfeaturesManipulatingstringsJoiningandcomparingstringsCopyingandswappingstringsFindingsubstringsFormattingstringsFormattingdatestringsSummary
DiscoveringstringfeaturesTheC#Stringclasslibraryprovidespropertiesandmethodsthatenableaprogramtoeasilydiscoverfeaturesofatextstring.Usefully,theString.IsNullOrWhiteSpace()andString.IsNullOrEmpty()methodscanbeusedtovalidateuserinput.Thesearestaticmethods,soarewrittendot-suffixedtotheStringclassname.
StringclassmethodscanbewrittenusingtheString.classprefixoritsstring.aliasprefix–ourexamplesuseStringtodifferentiatefromthestringdatatype.
Otherpropertiesandmethodsoperateonan“instance”oftheclass,soarewrittendot-suffixedtoastringvariablename.Instancemethodscanreportstringsizeandqueryitscontents.TheLengthpropertyreturnsanintegerthatisthenumberofcharacterswithinthestring,includingspaces.Additionally,theStartsWith(),EndsWith(),andContains()methodscaneachacceptastringargumenttomatchwithinthestringvariablevalue.Whenamatchisfound,theyreturntrue,otherwisetheyreturnfalse:
Features
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Features”
TypethesestatementsrequestinguserinputtoinitializeastringvariableConsole.Write(“PleaseEnterText:”);stringtext=Console.ReadLine();
Next,addaconditionaltesttoensuretheuserenteredinputbeforehittingtheEnterkeyif(String.IsNullOrWhiteSpace(text)){Console.WriteLine(“\nERROR:NoTextFound!”);
}else{//Statementstobeinsertedhere(Steps4-7).
}Console.ReadKey();
Now,insertstatementstoreportthelengthofthestringConsole.WriteLine(“\nThanks.YouEntered:\n’”+text+”’”);Console.WriteLine(“\nTextLength:”+text.Length);
Insertanotherstatementtotesthowthestringbeginsstringquery=text.StartsWith(“C#”)?“Does”:“DoesNot”;Console.WriteLine(“Text”+query+“StartWith‘C#’”);
MethodswithaString.(orstring.)prefixareusingtheStringclassitself,whereasdot-suffixedmethodsusean“instance”objectoftheclass–seeChapterNine.
Notethatsomeofthesestringsinclude‘singlequoteswithintheouter“doublequotemarks.
Next,insertastatementtotesthowthestringendsquery=text.EndsWith(“steps”)?“Does”:“DoesNot”;Console.WriteLine(“Text”+query+“EndWith‘steps’”);
Now,insertastatementtotestwhatthestringcontainsquery=text.Contains(“easy”)?“Does”:“DoesNot”;Console.WriteLine(“Text”+query+“Contain‘easy’”);
PressStartorF5toruntheapplication,andhitEnterwithoutinputtoseetheerrormessage
PressStartorF5toruntheapplicationagain,typeinputthenhitEntertodiscoverinputstringfeatures
Noticethatthe?:ternaryoperatorisusedheretoassignanappropriatestringvalue.
Stringvaluesareoftenreferredtoas“literals”,astheycomprisecharacterstobereadliterally,astext.
ManipulatingstringsTheC#Stringclasslibraryprovidesmethodsthatenableaprogramtomanipulatetextstrings.TheToLower()andToUpper()methodscanbedot-suffixedtoastringvariabletochangeallcharacterswithinthestringtolowercase,ortouppercase.
Similarly,theTrimStart(),TrimEnd(),andTrim()methodscanbeusedtoremovewhitespace,orothercharacters,fromastringatitsstart,end,orbothstartandend.Bydefault,thesemethodswillremovewhitespacefromthestring,butyoucanalternativelyspecifyacharactertoberemovedasanargumenttothemethod.
Youcanalsospecifymultiplecharacterstobetrimmedasacomma-separatedlistofargumentstotheTrimStart(),TrimEnd(),orTrim()methods.
Conversely,thePadLeft()andPadRight()methodscanbeusedtoaddwhitespace,orothercharacters,ontoastringatitsstartorend.Theirargumentsmustspecifythetotalcharacterlengthofthepaddedstring,andapaddingcharacterunlessdefaultwhitespacepaddingisrequired.Ifyouwanttoaddpaddingontobothstartandend,themethodscanbe“chained”asPadLeft().PadRight()statingeachpaddinglengthargument,andcharacterifrequired:
Manipulate
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Manipulate”
TypethesestatementsrequestinguserinputtoinitializeastringvariableConsole.Write(“PleaseEnterText:”);stringtext=Console.ReadLine();
AddstatementstodisplaytheuserinputstringandreportitslengthConsole.Write(“\nThanks.YouEntered:\n’”+text+”’”);Console.WriteLine(“\t\tTextLength:”+text.Length);
Removeleadingandtrailingwhitespace,thendisplaythemanipulatedversionandreportitslengthtext=text.Trim();Console.Write(“\nTrimmed:\t’”+text+”’”);Console.WriteLine(“\tTextLength:”+text.Length);
Next,addstatementstocreateanddisplayanuppercaseversionofthetrimmedstringstringupper=text.ToUpper();Console.WriteLine(“\nUpperCase:\t’”+upper+”’”);
ItisagoodideatoalwaysuseTrim()toremovespacesaccidentallyaddedbytheuserwhentypinginput.
Now,createanddisplayalowercaseversionofthetrimmedstringstringlower=text.ToLower();Console.WriteLine(“LowerCase:\t’”+lower+”’”);
Then,furthermanipulateallthreestringstoaddwhitespaceandcharacterpaddingupper=upper.PadLeft(40);lower=lower.PadRight(40,‘#’);text=text.PadLeft(30,‘*’).PadRight(40,‘*’);
AddstatementstodisplayallthreestringstoseethepaddedwhitespaceandpaddedcharactersConsole.WriteLine(“\nPaddedLeft:\t’”+upper+“’”);Console.WriteLine(“PaddedRight:\t’”+lower+“’”);Console.WriteLine(“PaddedBoth:\t’”+text+“’”);
Finally,addstatementstodisplaytrimmedversionsoftwopaddedstringsConsole.WriteLine(“\nTrimmedStart:\t’”+upper.TrimStart()+“’”);Console.WriteLine(“TrimmedEnd:\t’”+text.TrimEnd(‘*’)+“’”);Console.ReadKey();
PressStartorF5toruntheapplicationandenterastringwithleadingandtrailingspacetoseeitmanipulated
Here,allthreestringsareexpandedtoatotalwidthof40characters.
Whenpaddingbothleftandrightyoumustindividuallyspecifybyhowmuchtoexpandthestringineachdirection–inthiscaseexpandingfrom20to30charactersleft,thenfrom30to40charactersright.
JoiningandcomparingstringsWhenthe+operatorisusedtoconcatenate(join)stringsinanassignment,thecombinedstringsgetstoredinthestringvariable.ButwhenusedintheWrite()orWriteLine()methods,thestringsareonlycombinedinoutput–thevariablevaluesareunchanged.
TheC#StringclasslibraryprovidesaString.Concat()methodthatcanbeusedtojoinstringsasanalternativetousingthe+operator.Thismethodacceptsacomma-separatedlistofstringargumentstobejoinedintoasinglestring.
Theexamplesinthisbookusethe+operatorforconcatenationratherthanString.Concat()asitprovidesbetterreadabilitywithoutanylossofperformance.
Similarly,theString.Join()methodcanalsobeusedtojoinstringsasanalternativetousingthe+operator.Thistooacceptsacomma-separatedlistofstringargumentstobejoined,butitsfirstargumentusefullyspecifiesaseparatorstring.Itplacesthisseparatorbetweeneachotherstringargumentinthejoinedstring.Theseparatormightbeasinglespacetoseparatewords,orperhapsanHTMLtagtoseparatetext,oranyotherstringvalue.
StringcomparisonscanbemadeforalphabeticorderbyspecifyingtwostringargumentstotheString.Compare()method.Thisreturnsanintegerdenotingwhetherthealphabeticrelationshipofthefirststringtothesecondisbefore(-1),after(1),orequal(0).ThereisalsoaCompareTo()methodthatprovidesthesameresults,butthiscanbedot-suffixedontothefirststring,andthesecondstringspecifiedasitsargument.
Aswithnumericcomparisons,the==operatorcanbeusedtotestforstringequality.Alternatively,theEquals()methodcanbedot-suffixedontothefirststring,andthesecondstringspecifiedasitsargument.EitherwillreturnatrueorfalseBooleanresult.
Joined
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Joined”
Typethisstatementtocreateandinitializeastringarrayvariablesimplynamed“a”string[]a=newstring[3]{“Alpha”,”Bravo”,”Charlie”};
Next,assignaconcatenatedversionofthefirsttwoarrayelementvaluestoastring
variableanddisplayitsvaluestrings=String.Concat(a[0],a[1]);Console.WriteLine(“Concatenated:\t”+s);
Assignajoinedversionofthefirsttwoarrayelementsandspaceseparatortothestringvariable,thendisplayitsvalues=String.Join(““,a[0],a[1]);Console.WriteLine(“Joined:\t\t”+s);
Assignajoinedversionofallthreearrayelementsandtagseparatortothestringvariable,thendisplayitsvalues=String.Join(“<br>“,a);Console.WriteLine(“\nHTML:\t”+s+”\n”);
Next,addstatementstocompare,inturn,allthreearrayelementsforalphabeticorderintnum=String.Compare(a[0],a[1]);Console.WriteLine(a[0]+”v“+a[1]+”:\t”+num);
num=String.Compare(a[2],a[1]);Console.WriteLine(a[2]+”v“+a[1]+”:\t”+num);
num=a[1].CompareTo(a[1]);Console.WriteLine(a[1]+”v“+a[1]+”:\t”+num+“\n”);
Finally,testthearrayelementvaluesforequalityboolflag=(a[0]==a[1]);Console.WriteLine(a[0]+”==“+a[1]+”:\t\t”+flag);flag=a[2].Equals(a[2]);Console.WriteLine(a[2]+”==“+a[2]+”:\t\t”+flag);Console.ReadKey();
PressStartorF5toruntheapplicationtoseethejoinedstringsandcomparisonresults
Noticehowonlythearraynameneedstobespecifiedastheargumenttojoinallthreearrayelements.
Youcanaddorremovethe\tescapesequencestoformattheoutputtoyourliking.
Twoalternativemethodsareusedheretocomparestringsandtotestforequality.
CopyingandswappingstringsTheC#StringclasslibraryprovidesaString.Copy()methodthatcanbeusedtocopyonestringtoanotherstringasanalternativetousingthe=assignmentoperator.Thismethodacceptsthestringtobecopiedasitsargument.Perhapsmoreusefully,theCopyTo()methodcanbedot-suffixedontoastringvariabletocopyitscontentsintoacharcharacterarray.Thisrequiresfourargumentstospecifytheindexnumberfromwhichtostartcopyinginthesourcestring,thenameofthechararray,theindexnumberatwhichtostartcopyinginthedestinationchararray,andthenumberofcharacterstocopy.
Copyingwithan=assignmentproducestwostringvariablesthatcontainthesamevalueandreferencethesamememorylocation,whereascopyingwiththeString.Copy()methodproducestwostringvariablesthatcontainthesamevaluebutreferencedifferentmemorylocations.
Othermethodscanbedot-suffixedtoastringvariabletoswapitscontents.TheRemove()methodrequiresanintegerargumenttospecifytheindexnumberatwhichtobeginremovingcharactersfromthestring.Thiswillremoveallcharactersfromthespecifiedindexpositionuptotheendofthestring,unlessyouaddasecondargumenttospecifythenumberofcharacterstoberemoved.
Conversely,theInsert()methodrequiresanintegerargumenttospecifytheindexnumberatwhichtobegininsertingcharactersintothestring,andanargumentspecifyingthestringtoinsert.TheReplace()methodsimplyrequirestwostringargumentstospecifyasubstringtoseekwithinthestring,andastringtoreplacethatsubstringwhenamatchisfound:
Copied
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Copied”
TypethesestatementstocreateandinitializetwostringvariableswiththenamesoftwoMaseraticarmodelsstringcar1=“Ghibli”;stringcar2=“GranTurismo”;
Next,displaytheoriginalvaluescontainedineachvariableConsole.WriteLine(“Original:”);Console.WriteLine(“\tCar1:”+car1+“\t\tCar2:“+car2);
Now,copythevalueofthesecondstringvariableintothefirststringvariableanddisplaytheirmodifiedvaluescar1=String.Copy(car2);Console.WriteLine(“\nCopied:”);Console.WriteLine(“\tCar1:”+car1+“\tCar2:“+car2);
Initializeanintegervariablewiththelengthofthefirststringvariable,thencreateacharacterarrayofthatlengthintnum=car1.Length;char[]model=newchar[num];
Next,copythefirststringvariableintothecharacterarray,thendisplayaspace-separatedlistoftheelementcontentscar1.CopyTo(0,model,0,num);Console.WriteLine(“\nCharacterArray:”);foreach(charcinmodel){Console.Write(c+““);}
Now,removetheendofthefirststringvariable,startingfromitsfifthelement,anddisplaythemodifiedvaluecar1=car1.Remove(4);Console.WriteLine(“\n\nRemoved...\tCar1:”+car1);
Inserttwostringsintothefirststringvariable,atitsbeginningandend,thendisplaythemodifiedvaluecar1=car1.Insert(0,“Maserati”);car1=car1.Insert(13,“Cabrio”);Console.WriteLine(“\nInserted...\tCar1:”+car1);
Finally,replaceasubstringwithinthefirststringvariable,andoncemoredisplaythemodifiedvaluecar1=car1.Replace(“GranCabrio”,“Quattroporte”);Console.WriteLine(“\nReplaced...\tCar1:”+car1);Console.ReadKey();
PressStartorF5toruntheapplicationtoseethecopiedandswappedstrings
Thechararraymustbeofthesamesizeasthestringtobecopied–usethestring’sLengthpropertytospecifythesizeofthechararray.
Thefifthelementofanarrayisatindexposition4inazero-basedindex.
FindingsubstringsTheC#Stringclasslibraryprovidesanumberofmethodsthatcanbedot-suffixedtoastringvariabletoseekastringwithinastring(i.e.a“substring”).TheIndexOf()methodrequiresthesubstringasitsargumentand,iffound,returnstheindexpositionofthesubstringwithinthesearchedstring.Otherwiseitwillreturn-1.TheIndexOf()methodsearchesforwards,fromleft-to-right,andreturnstheindexpositionofthefirstoccurenceofthesubstring.IthasacompanionLastIndexOf()methodthatworksinjustthesameway,butsearchesbackwards,fromright-to-left.
Thepositionreportedwhenasubstringisfoundistheindexpositionofthefirstcharacterofthatsubstringwithinthesearchedstring–whethersearchingforwardsorbackwards.
Similarly,thereisanIndexOfAny()methodanditscompanionLastIndexOfAny()methodthatrequireacharacterarrayargument.Theseseekanycharacterofthespecifiedarraywithinastring,andreturntheindexpositionofthefirstoccurrence,or-1otherwise.
Youcanalsodot-suffixaSubstring()methodtoastringvariableifyouwanttoextractacopyofasubstringfromwithinthatstring.Thismethodrequirestwoargumentstospecifytheindexpositionatwhichtobegincopying,andthenumberofcharacterstocopy:
Substring
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Substring”
AftertheMain()method,addthismethoddeclarationtoreporttheresultofasubstringsearchstaticvoidreport(intpos,stringsub){if(pos!=-1){Console.WriteLine(“‘“+sub+”’FoundAt“+pos);}else{Console.WriteLine(“‘“+sub+”’NotFound!“);}
}
Now,turnyourattentiontotheMain()methodandinitializeastringvariable,thendisplayitsvalueandlengthstringtext=“Mydogisacutedog”;
Console.WriteLine(text+”\tLength:“+text.Length);
Next,requestuserinputtoinitializeanotherstringvariablewithasubstringtoseekConsole.WriteLine(“\nPleaseEnterASubstringToSeek:”);stringsub=Console.ReadLine();
Createacharacterarrayandcopytheentiresubstringvalueintothecharacterarraychar[]arr=newchar[sub.Length];sub.CopyTo(0,arr,0,sub.Length);
Then,seekthefirstoccurrenceofthesubstringandcallthemethodyoudefinedtoreportthesearchresultintpos=text.IndexOf(sub);report(pos,sub);
Now,seekthelastoccurrenceofthesubstringandreporttheresultpos=text.LastIndexOf(sub);report(pos,sub);
Next,seekthefirstoccurrenceofanycharacterofthesubstringandreporttheresultpos=text.IndexOfAny(arr);report(pos,text.Substring(pos,1));
Finally,seekthelastoccurrenceofanycharacterofthesubstringandreporttheresultpos=text.LastIndexOfAny(arr);report(pos,text.Substring(pos,1));Console.ReadKey();
PressStartorF5toruntheapplication,thenenterasubstringtoseekandseethereportedresults
TheCopyTo()methodisdescribedanddemonstratedinthepreviousexamplehere.
NoticethatacopyofthelocatedcharacterisextractedfromtheoriginalstringusingtheSubstring()methodforoutputinthereport.
FormattingstringsInC#everyobjecthasaToString()methodthatreturnsastringrepresentationofthatobject.ThismeansthattheToString()methodcanbedot-suffixedtoanynumericvariabletogetitsvaluerepresentedinstringformat.TheToString()methodcan,optionally,acceptastringargumenttospecifyhowthestringversionshouldbeformatted.Commonspecifiersarelistedbelow:
Specifier: Returns:
G General
F FixedPoint
N Number(withcomma-separatedthousands)
C Currency(prevailingonyoursystem)
P Percentage(multipliedby100)
00.0000 ZeroPadding
TheC#specificationsprovidefurtherstringformattingspecifieroptionsinadditiontothecommonlyusedonesshownhere.
TheC#StringclasslibraryprovidesaString.Format()methodthatusesthesamespecifierstoalsoproducevaluesrepresentedinstringformat.Thisrequiresanargumenttospecifythestringtobeformatted,whichmayinclude“placeholders”,andanargumentlisttobesubstitutedforeachplaceholderintheoutputstring.
Multipleplaceholdersinonestringcanbenumberedalike–ifyouwanteachonetobesubstitutedbythesamelistargumentvalue.
Eachplaceholdercanbenumberedsequentially(startingatzero)within{}braces,tomatchthelistpositionofthesubstitutionargument.Forexample,{0}matchesthefirstargumentinthesubstitutionargumentlist,{1}matchesthesecond,andsoon.Additionally,thenumbermaybefollowedbya:colonandoneoftheformatspecifiersinthetableabove–tospecifyhowthe
substitutedvalueshouldappearinitsstring.Forexample,{0:G}.
Datastringsthatcontainseparators,suchasacomma-separatedlistofdataretrievedfromadatabasequery,canbeeasilybrokenintoindividualitemsofdatabydot-suffixingtheSplit()methodtoastringvariable.Theindividualstringscanbeassignedtoastringarrayvariable,andcouldthenbeformattedinoutputbytheString.Format()methodifrequired.
Format
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Format”
Initializeanumericvariable,thenusetheToString()methodtooutputitsvalueasacurrencystringformatintsum=2500;Console.WriteLine(“CurrencyString:“+sum.ToString(“C”));
Next,usetheString.Format()methodtooutputthesamenumericvalueinvariouscommonstringformatsConsole.Write(String.Format(“\nGeneral:\t{0:G}”,sum));Console.Write(String.Format(“\nFixedPoint:\t{0:F}”,sum));Console.Write(String.Format(“\nNumber:\t\t{0:N}”,sum));Console.Write(String.Format(“\nCurrency:\t{0:C}”,sum));
Now,reducethenumericvalue,thenoutputitinapercentagestringformatandwithpaddedzeroessum/=1000;Console.Write(String.Format(“\nPercentage:\t{0:P}”,sum));Console.Write(String.Format(“\nZeroPadded:\t{0:00.0000}\n”,sum));
Then,createacomma-separatedstringlistandsplititintoindividualelementsofastringarrayvariableforoutputstringdata=“Mike,McGrath,Author”;string[]items=data.Split(‘,’);foreach(stringiteminitems){Console.Write(String.Format(“\n*{0}”,item));}Console.ReadKey();
PressStartorF5toseetheformattedstringoutput
Thespecifierlettersmaybewrittenaseitheruppercaseorlowercase.
TheargumenttotheSplit()methodmustbeasinglecharcharacter–enclosedinsinglequotes.
Youcanusethe+concatenationoperatorforformatting,butmanypreferString.Format()foreasilyreadablecode.
FormattingdatestringsTheC#DateTimeclasslibraryprovidesmethodsandpropertiestoeasilyworkwithdatesandtimes.ItsNowpropertyreturnsaDateTimeobjectofthecurrentlocaldateandtimeofyoursystem.Alternatively,youcancreateaDateTimeobjectusingthenewkeyword,andspecifyingadateandtimeasacomma-separatedlistofarguments.Manymethodsandpropertiescanbedot-suffixedtoanyDateTimeobjecttospecifyitsformat,ortoextractspecificcomponentsofthedateortime,ortomodifyitsvalue.Forexample,theDayOfWeekpropertysuppliesthedayname,theToShortString()methodsuppliesthedateinnumberform,andtheAddYears()methodcanmodifytheyearcomponent.
YoucanuseIntelliSensetochoosemethodsandproperties–forexample,typeDateTime.Now.andselectfromthepop-uplistthatappears.
TheString.Format()method,introducedinthepreviousexample,alsohasthesespecifiersthatcanbeusedtodeterminetheformatofdatesandtimesinoutput:
Specifier: Returns: Example:
d Shortdate 7/4/2017
D Longdate Tuesday,July4,2017
t Shorttime 8:15AM
T Longtime 8:15:30AM
f Fulldatetime Tuesday,July4,20178:15AM
F Full+seconds Tuesday,July4,20178:15:30AM
M Month+day July4
Y Month+year July2017
dd Daynumber 04
dddd Dayname Tuesday
HH Hour0-23 08
mm Minute 15
ss Second 30
YYYY Year 2017
TheC#specificationsprovidefurtherdateandtimeformattingspecifieroptionsinadditiontothecommonlyusedonesshownhere.
DateFormat
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“DateFormat”
InitializeaDateTimeobjectanddisplayitsvalueDateTimenow=DateTime.Now;Console.Write(“CurrentDateAndTime:“+now);
Next,displayspecificcomponentsoftheDateTimeobjectConsole.Write(“\nDayName:“+now.DayOfWeek);Console.Write(“\nDateOnly:“+now.ToShortDateString());Console.Write(“\nTimeOnly:“+now.ToShortTimeString());
ModifytheDateTimeobjectanddisplayitsnewvaluenow=now.AddYears(4);Console.Write(“\n\nFutureDate:“+now);
Now,createanewDateTimeobjectanddisplayitsvalueDateTimedt=newDateTime(2017,7,4,8,15,30);Console.Write(“\n\nSetDateAndTime:{0:f}“,dt);
DisplayspecificcomponentsofthenewDateTimeobjectConsole.Write(“\nDayName:{0:dddd}“,dt);Console.Write(“\nLongDate:{0:D}“,dt);Console.Write(“\nLongTime:{0:T}“,dt);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheformatteddateandtimeoutput
YouneedonlyspecifythedatecomponentswhencreatinganewDateTimeobject–thetimewillautomaticallybesetto12:00AM(midnight).
Summary• Classlibrarystaticmethods,suchasString.IsNullOrEmpty(),aredot-suffixedontotheStringclass
libraryname.
• StringvaluescanbejoinedusingtheString.Concat()andString.Join()methods,orusingthe+concatenationoperator.
• StringcomparisonscanbemadeforalphabeticorderusingtheString.Compare()method.
• AvaluecanbecopiedfromonestringvariabletoanotherusingtheString.Copy()method,or=assignmentoperator.
• TheString.Format()methodcanbeusedtoformatbothnumericanddatestringsinoutput.
• TheDateTimeclasslibraryprovidesmethodsandproperties,suchasNow,toworkwithdateandtimestrings.
• Instancemethodsandproperties,suchasContains()andLength,aredot-suffixedontostringvariablenames.
• ThecharactercaseofastringvaluecanbechangedusingtheToLower()andToUpper()methods.
• Whitespace,orothercharacters,canberemovedfromastringvalueusingtheTrimStart(),TrimEnd(),andTrim()methods.
• Whitespace,orothercharacters,canbeaddedtoastringvalueusingthePadLeft()andPadRight()methods.
• StringcomparisonscanbemadeusingtheCompareTo()andEquals()methods,orthe==equalityoperator.
• AstringvaluecanbecopiedfromastringvariableintoachararrayusingtheCopyTo()method.
• ThecontentsofastringvariablecanbeswappedusingtheRemove(),Insert(),andReplace()methods.
• AsubstringcanbesoughtusingIndexOf(),LastIndexOf(),IndexOfAny(),LastIndexOfAny(),andSubstring()methods.
• EveryobjecthasaToString()methodthatreturnsastringrepresentation,whichcanbeformattedinoutput.
7
Accessingfiles
ThischapterdemonstrateshowC#programscanstoredataintextfiles,andretrievedatafromtextfiles.
WritingafileAppendingtoafileReadingtextandlinesStreaminglinesManipulatinginputandoutputSummary
WritingafileTheC#System.IO.Fileclasslibraryprovidesmethodsthatenableaprogramtoeasilywritetextintoafileonyourcomputer.TheSystem.IOclassisnotautomaticallylistedinthedefaultusingdirectivegeneratedbyVisualStudio.ThismeansyoumustincludetheSystem.IOprefixwhenusingFilemethodsor,moreconveniently,addafurtherusingdirectivesotheprefixmaythenbeomittedinyourprogramcode:
usingSystem.IO;
TheFile.WriteAllText()methodsimplyrequirestwoargumentstospecifythetextfilepathandthestringtowrite.Backslashcharactersinthepathstringmustbeescapedtoavoidanerror.
Ifyouwouldliketoensurethespecifiedtextfiledoesnotalreadyexist,youcanfirsttestforitsexistencebyspecifyingitspathastheargumenttotheFile.Exists()method.Thiswillreturntruewhenthefileisfound,otherwiseitwillreturnfalse.
Ifyoudon’taddtheusingSystem.IO;statementyoumustwriteSystem.IO.File.WriteAllText()andSystem.IO.File.Exists()tocallthesemethods.
Inordertoensurethetextfilewaswrittensuccessfully,itisworthwhilewrappingtheFile.WriteAllText()callinatry-catchblock.Astatementconfirmingsuccesscanbeincludedinthetrypartoftheblock,andastatementtoadviseoffailurecanbeincludedinthecatchpartoftheblock:
WriteText
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“WriteText”
TypethisdirectiveabovethenamespacedeclarationtomakeafurtherclasslibraryavailabletotheprogramusingSystem.IO;
BackintheMain()method,addthesestatementstoinitializetwovariables–insertyourownusernamewhereindicatedinthepath//Editthelinebelowtoincludeyourusername.stringpath=“C:\\Users\\username\\Desktop\\poem.txt”;stringpoem=“\r\n\tIneversawamanwholooked”;poem+=“\r\n\tWithsuchawistfuleye”;
poem+=“\r\n\tUponthatlittletentofblue”;poem+=“\r\n\tWhichprisonerscallthesky”;
The\r\n\tescapesequenceisacarriagereturn,newline,andtab.
Next,addastatementtotestifafilealreadyexistsofthespecifiedpathandfilenameif(File.Exists(path)){Console.WriteLine(“FileAlreadyExists:“+path);
}else{//Statementstobeinsertedhere(Step5).
}Console.ReadKey();
Now,insertstatementsthatattempttowriteatextfileandconfirmsuccess,oradviseoffailuretry{File.WriteAllText(path,poem);Console.WriteLine(“FileWritten:“+path);
}catch(Exceptionerror){Console.WriteLine(error.Message);
}
PressStartorF5toruntheapplicationandseeatextfilewrittenonyourDesktop,orseeanerrormessage
Catchingexceptionswiththetry-catchblockisfullydescribedinthenextchapterdealingwithproblemsolving–seehere.
Runthisapplicationagaintoseethemessageadvisingthatthefilealreadyexists.
AppendingtoafileTheC#System.IO.FileclasslibraryprovidesaWriteAllLines()methodthatcanbeusedtowritethecontentsofastringarraytoatextfile,witheachelementappearingonaseparateline,andatry-catchblockcanensurethetextfilewaswrittensuccessfully.
Additionally,theSystem.IO.FileclasshasanAppendAllText()method,whichcanbeusedtoaddtexttoanexistingfile,andtheFile.Exists()methodcanensurethatthefilefirstexists:
AppendText
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“AppendText”
TypethisdirectiveabovethenamespacedeclarationtomakeafurtherclasslibraryavailabletotheprogramusingSystem.IO;
BackintheMain()method,addthesestatementstoinitializethreevariables–insertyourownusernamewhereindicatedinthepathstringpath=“C:\\Users\\username\\Desktop\\oscar.txt”;string[]poem=newstring[]{“\tInDebtors’Yardthestonesarehard”,“\tAndthedrippingwallishigh”
};stringattrib=“\r\n\tTheBalladOfReadingGaol”;attrib+=“(OscarWilde1898)”;
Next,addastatementtotestifafilealreadyexistsofthespecifiedpathandfilenameif(File.Exists(path)){//Statementstobeinsertedhere(Step5).
}else{//Statementstobeinsertedhere(Step6).
}Console.ReadKey();
Now,insertstatementsthatattempttoappendtextifthefilealreadyexists,andadviseofsuccessFile.AppendAllText(path,attrib);Console.WriteLine(“AppendedToFile:“+path);
The\r\ncharacterreturn,newlineescapesequencescanbeomittedfromthestringarray,astheWriteAllLines()methodautomaticallywriteseachelementonnewlines.
Then,insertstatementsthatattempttowriteatextfileandconfirmsuccess,oradviseoffailuretry{File.WriteAllLines(path,poem);Console.WriteLine(“FileWritten:“+path);
}catch(Exceptionerror){Console.WriteLine(error.Message);
}
AswithWriteAllText(),theWriteAllLines()methodrequiresthetextfilepathandstringtowriteasitsarguments.
PressStartorF5toruntheapplicationandseeatextfilewrittenonyourDesktop,orseeanerrormessage
ThereisalsoanAppendAllLines()methodthatcanbeusedtoaddthecontentsofa
stringarraytoafile.
Runtheapplicationoncemoreandseeaconfirmationappearandseetextappendedtothefile
Afteritsfirstrun,thisapplicationwillappendtexteachtimeitisrun.
ReadingtextandlinesTheC#System.IO.FileclasslibraryprovidesaReadAllText()methodthatcanbeusedtoreadtextfromanexistingfileandassignitsentirecontentstoastringvariable.TheFile.Exists()methodcanensurethatthetextfilefirstexistsandatry-catchblockcanensurethefilewasreadsuccessfully.
Additionally,theSystem.IO.FileclasshasaReadAllLines()method,whichcanbeusedtoassigneachlineofatextfiletoanindividualelementofastringarray:
ReadText
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“ReadText”
TypethisdirectiveabovethenamespacedeclarationtomakeafurtherclasslibraryavailabletotheprogramusingSystem.IO;
BackintheMain()method,addthisstatementtoinitializeavariable–insertyourownusernamewhereindicatedinthepathstringpath=“C:\\Users\\username\\Desktop\\word.txt”;
Next,addastatementtotestifafilealreadyexistsofthespecifiedpathandfilenameif(File.Exists(path)){//Statementstobeinsertedhere(Step5).
}else{Console.WriteLine(“FileNotFound:“+path);
}Console.ReadKey();
Now,insertastatementtodisplayamessageifthefilecannotbereadsuccessfullytry{//Statementstobeinsertedhere(Steps6and7).
}catch(Exceptionerror){Console.WriteLine(error.Message);
}
Whenatextfileisreadintoastringarray,thearray’sLengthproperty,whichreturnsthenumberofitselements,willrepresentthenumberoflinesread–includingemptylines!
Then,insertstatementstoassignthetextfilecontentstoavariableanddisplayitsvaluestringtext=File.ReadAllText(path);Console.WriteLine(“FileRead:“+path+“\n”);Console.WriteLine(text+“\n”);
Finally,insertstatementstoassignthetextfilecontentstoanarrayvariableanddisplayeachelementwithacounterstring[]lines=File.ReadAllLines(path);intnum=1;foreach(stringlineinlines){Console.WriteLine(num+“:”+line);num++;
}
Openatexteditor,suchasNotepad,andcreateamulti-linetextfilenamed“word.txt”onyourDesktop
PressStartorF5toruntheapplicationandseeatextfilereadfromyourDesktop,orseeanerrormessage
Thetextfile’sinvisiblenewlineandtabcharactersarepreservedwhenreadbytheReadAllText()method,butonlytheinvisibletabcharactersarepreservedwhenitisreadbytheReadAllLines()method.
Removethetextfiles’ReadandReadWritepermissionsonyoursystemandruntheapplicationagaintoseean“Accesstopathdenied”message.
StreaminglinesTheFile.WriteAllText()andFile.AppendAllText()methodsaresimpletousebutprovidefewoptions.TheSystem.IO.StreamWriterclassalsoprovidesobjectmethodsthatcanbeusedtowritetexttoafile,andtheseprovidemoreoptions.AninstanceofaStreamWriterobjectmustfirstbecreatedusingthenewkeywordandthetextfilepathspecifiedasanargumenttoits“constructor”methodlikethis:
StreamWritername=newStreamWriter(path);
Methods,suchasWrite()andWriteLine()canthenbedot-suffixedtotheobjectname.AStreamWriterobjectisdisposable,soitsstatementsarebestenclosedwithinausingconstructtoensureitisremovedfrommemoryuponcompletion,likethis:
using(StreamWritername=newStreamWriter(path)){//Statements.
}
Theusingkeywordhasdifferentmeaningsaccordingtoitscontext.
Theusingconstructcanalsobewrappedinatry-catchblock,toensurethetextfilewaswrittensuccessfully.Optionally,theStreamWriterconstructorcanacceptasecondargumentoftruetoappendtoexistingtext:
WriteStream
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“WriteStream”
TypethisdirectiveabovethenamespacedeclarationtomakeafurtherclasslibraryavailabletotheprogramusingSystem.IO;
BackintheMain()method,addthesestatementstoinitializethreevariables–insertyourownusernamewhereindicatedinthepathstringpath=“C:\\Users\\username\\Desktop\\robert.txt”;stringpoem=newstring[]{“\tThistruthfindshonestTamo’Shanter”,
“\tAshefromAyronenightdidcanter”,“\tOldAyr,whichneveratownsurpasses”,“\tForhonestmenandbonnielasses.”
};stringattrib=“\r\n\tTamO’Shanter(RobertBurns1790)”;
Next,addastatementtodisplayamessageifthefilecannotbewrittensuccessfullytry{//Statementstobeinsertedhere(Steps5and6).
}catch(Exceptionerror){Console.WriteLine(error.Message);}Console.ReadKey();
Now,insertstatementsthatattempttowritethecontentsofthevariablearrayintoatextfileusing(StreamWriterwriter=newStreamWriter(path)){foreach(stringlineinpoem){writer.WriteLine(line);}
}
Finally,insertstatementsthatattempttoappendthecontentsoftheregularvariableintoatextfileusing(StreamWriterwriter=
newStreamWriter(path,true)){writer.WriteLine(attrib);Console.WriteLine(“FileWritten:“+path);}
}
PressStartorF5toruntheapplicationandseeatextfilewrittenonyourDesktop,orseeanerrormessage
TheusingconstructensurestheStreamWriterisdisposedofwhenitsoperationscomplete,sothesamenamecanbeusedforthenewobject.
Trywritingthisfileintoaread-onlydirectorytoseean“Accesstopathdenied”message.
ManipulatinginputandoutputTheSystem.IO.StreamReaderclassprovidesobjectmethodsthatcanbeusedtoreadtextfromafile.AninstanceofaStreamReaderobjectmustfirstbecreatedusingthenewkeywordandthetextfilepathspecifiedasanargumenttoits“constructor”:
StreamReadername=newStreamReader(path);
MethodssuchasRead()andReadLine()canthenbedot-suffixedtotheobjectname.AStreamReaderobjectisdisposable,soitsoperationstatementsarebestenclosedwithinausingconstructtoensureitisremovedfrommemorywhentheoperationhascompleted.Theusingconstructcanalsobewrappedinatry-catchblock,toensurethetextfilewasreadsuccessfully.
TextreadbyaStreamReaderobjectcanbemanipulatedtochangeitsformatbeforeoutput.Forexample,tomanipulatecellsexportedfromanExcelspreadsheetascomma-separatedvalues:
ReadStream
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“ReadStream”
TypethisdirectiveabovethenamespacedeclarationtomakeafurtherclasslibraryavailabletotheprogramusingSystem.IO;
BackintheMain()method,addastatementtoinitializeavariable–insertyourownusernameinthepathstringpath=“C:\\Users\\username\\Desktop\\TopFive.csv”;
Next,addastatementtodisplayamessageifthefilecannotbereadsuccessfully
try{//Statementstobeinsertedhere(Step5).
}catch(Exceptionerror){Console.WriteLine(error.Message);}Console.ReadKey();
Now,insertstatementsthatattempttoreadthecontentsofthetextfileintoavariable,linebylineusing(StreamReaderreader=newStreamReader(path)){stringline;while((line=reader.ReadLine())!=null){//Statementstobeinsertedhere(Steps6-7).
}}
Insertstatementstomodifythecaseofthecolumnheadersandamendanartistnameif(line.IndexOf(“Rank”)!=-1)line=line.ToUpper();if(line.IndexOf(“Sia”)!=-1)line+=“ft.SeanPaul”;
Finallyinsertstatementsthatdisplaythecontentofjusttwocolumns,formattedforalignment
string[]sub=line.Split(‘,’);line=String.Format(“{0,-30}{1,-20}”,sub[1],sub[2]);Console.WriteLine(line);
PressStartorF5toruntheapplicationandseethemanipulatedoutputfromthefilecontent
WhentheReadLine()methodreachestheendofthefilebeingread,itreturnsanullvalue.
TheString.Format()placeholdersspecifycharacterwidthsasnegativenumberstoalignstringstotheleft.
Summary• TheSystem.IOclassisnotautomaticallylistedintheusingdirectivesgeneratedbyVisual
Studio,soitmustbeaddedmanuallywithausingSystem.IO;statement.
• TheSystem.IO.Fileclassprovidesmethodstoeasilyreadorwritetextfilesonyourcomputer.
• TheSystem.IO.File.WriteAllText()methodrequirestwoarguments,tospecifyafilepathandcontenttowritethere.
• TheSystem.IO.File.Exists()methodwilldetermineifthefilespecifiedasitsargumentalreadyexists.
• Itisrecommendedallreadorwriteoperationsbewrappedinatry-catchblocktoreportwhenanattemptedoperationfails.
• TheSystem.IO.File.WriteAllLines()methodcanwritetheelementcontentofastringarrayasseparatelinesofafile.
• TheSystem.IO.File.AppendAllText()methodrequirestwoargumentstospecifyafilepathandcontenttoappendthere.
• TheSystem.IO.File.ReadAllText()methodcanbeusedtoassigntheentirecontentofatextfiletoastringvariable.
• TheSystem.IO.File.ReadAllLines()methodcanassignindividuallinesofatextfiletoelementsofastringarray.
• TheSystem.IO.StreamWriterclassprovidesobjectmethodstowritetextfilesonyourcomputer.
• TheSystem.IO.StreamReaderclassprovidesobjectmethodstoreadfromtextfilesonyourcomputer.
• AninstanceofaStreamReaderobjectorStreamWriterobjectiscreatedusingthenewkeywordandbyspecifyingafilepathwithintheparenthesesofitsconstructor.
• AStreamReaderobjecthasRead()andReadLine()methodsthatcanbedot-suffixedtoaninstancename.
• AStreamWriterobjecthasWrite()andWriteLine()methodsthatcanbedot-suffixedtoaninstancename.
• AllStreamReaderandStreamWriterobjectsaredisposable,soshouldeachbeenclosedinausingconstruct.
8
Solvingproblems
ThischapterdemonstrateshowtodetectandmanageerrorsinC#programs.
Detectingreal-timeerrorsFixingcompile-timeerrorsDebuggingcodeSettingbreakpointsCatchingrun-timeerrorsGettinghelpSummary
Detectingreal-timeerrorsAsyoutypecodeintheCodeEditorwindow,theVisualStudioIDEisconstantlymonitoringyourcodeforpossibleerrors.Itexaminesthecodeyoutypeandprovidesreal-timefeedbackofpossibleerrorsbyaddingawavyunderlinetoquestionablecode.
Warningsofpotentialproblemsareindicatedbyagreenwavyunderline.Thesearenotcriticalandwillnotpreventexecutionoftheapplication.ArolloverTooltipexplainsthewarning:
First,typethisvariabledeclarationintheCodeEditorintnum
Awavygreenlineappearsbelowthenumvariablename.Placethecursoroverthegreenwavyunderlinetodiscoverthatthewarningismerelyindicatingapotentialproblemasthevariablehasnotyetbeenassignedavalue
Errorsareindicatedbyaredwavyunderline.Unlikewarnings,thesearecriticalandwillpreventexecutionoftheapplication:
Next,typethisvariabledeclarationintheCodeEditorintnum=
Placethecursorovertheredwavyunderlinetodiscoverthattheerrorisduetoamissingvalueintheexpression
Warningscanbeignoredbuterrorsmustbecorrected.
Real-timeerrordetectionintheVisualStudioIDEisafantastictooltohelppreventerrorswhen
youarewritingcode.Itnotonlyindicateserrors,butcanevenprovidealistofcorrectionoptions:
Now,typethisvariabledeclarationintheCodeEditorintrnum=1;
Awavyredlineappearsbelowtheintrvariabletype.Placethecursorovertheredwavyunderlinetodiscoverthattheerrorisduetoanunknowntypespecification
Clickthelightbulbicon,orclicktheShowpotentialfixeslink,toseealistoferrorcorrectionoptions
Ifthiserrorissimplyaspellingerrorfortheintdatatype,selecttheoptiontoChange‘intr’to‘int’–seeyourcodegetinstantlycorrectedaccordingly
VisualStudio2015provideslivecodeanalysis,whichdisplaysalightbulbwhenthecompilerdetectsanissuewithyourcode,andhasasuggestionofhowtofixthatissue.
Othercorrectionoptionsallowyoutocreateanewdatatypeifthatiswhatyourequire.
Fixingcompile-timeerrorsWhilesyntaxerrorslikethoseherecanbedetectedbytheCodeEditorinreal-time,othererrorsthatemploycorrectsyntaxcannotbedetecteduntilthecodeiscompiled.Compileerrorsaretypicallyerrorsoflogic,andtheycausetheexecutiontohaltwhenan“exception”occurs.Forexample,whenincompatibledatatypesappearinanexpression,anInvalidCastExceptionoccursandexecutionstopsimmediately:
TypethefollowinglinesintotheCodeEditorboolflag=true;IConvertibleconvertible=flag;charletter=convertible.ToChar(null);
PressStartorF5toruntheapplicationandseeexecutionissoonhalted.ThelinecausingtheexceptionbecomeshighlightedintheCodeEditorandanExceptionAssistantpop-upwindowappearswithalistofpossiblesolutions
TheIConvertibleinterfaceprovidesmethodsthatconvertavaluetoaCLRtype,butitcannotmeaningfullyconvertabooltochar.
YoucanclickontheViewDetail...linkintheExceptionAssistant’sActions:listformoreerrorinformation.
TofixthisInvalidCastException,thecodewouldneedamendmentsobothvaluesareofcompatibledatatypes.
Thecauseofothercompileerrorsmaybelessobviouswithoutsomefurtherinvestigation.Forexample,whenaloopthatisreadingarrayelementsattemptstoaddressanelementindexthatdoesnotexist,causinganIndexOutOfRangeException.
Executionhaltsimmediately,soitisusefultoexaminethecountervaluetoidentifythepreciseiterationcausingthecompileerror.
IntheCodeEditor,typethefollowingvariablearraydeclarationoftenelements(0-9),andaloopint[]nums=newint[10];for(i=1;i<20;i++){nums[i]=i;}
PressStartorF5toruntheapplicationandseeexecutionissoonhalted.ThecodecausingtheexceptionbecomeshighlightedintheCodeEditorandanExceptionAssistantpop-upwindowappearswithalistofpossiblesolutions
Placethecursorovertheassignmenttothearrayvariabletoseeapop-upappeardisplayingitscurrentvalue
It’snowclearthatexecutionhaltedwhentheloopattemptedtoaddressnums[10]–beyondtheboundsoflastelementnums[9].TofixthisIndexOutOfRangeException,thecodewouldneedamendmenttoendtheloopafter10iterations.
AnothercommoncompileerroristheFileNotFoundExceptionthatoccurswhenafileismissingoritspathnameisincorrect.
DebuggingcodeItissometimesusefultocloselyexaminetheprogressionofaprogrambywatchingitsexecutionlinebylinetolocateanybugs.Progressiscontrolledbyclickingthe StepIntobuttonontheDebugMenuBartomovethroughtheprogramonelineatatime.WhenyoubegindebuggingyoucanopenaWatchwindowtomonitorthevalueofparticularvariablesasexecutionproceeds:
Debug
AddthefollowingcodewithintheMain()methodintpass=0;intunit=2;
for(inti=1;i<3;i++){pass=(pass+1);unit=square(unit);
}
Now,addthisarithmeticmethodaftertheMain()methodstaticintsquare(intnum){return(num*num);
}
IntheCodeEditor,clickinthegraymarginagainsttheMain()method–tosetadebugstarting“breakpoint”
ClicktheStepIntobuttononcetobegindebugging
ClickDebug,Windows,Watch,Watch1ontheMenuBartolaunchaWatchwindow
Typethevariablename“pass”intotheNamecolumnandhitEnter,thenrepeattoaddthe“unit”variablename
Ifyoucan’tseetheStepIntobutton,right-clickontheMenuBarandselectDebugtoaddthedebuggingbuttons.
YoucanclicktheStopDebuggingbuttonatanytimetoreturntoCodeEditormode.
ClickStepIntoseventimestoreachthesquare()methodcallinthefirstloopiteration,andnotethevalues
ClickStepInto10moretimestoprogressthrougheachlineofthesquare()methodandtheloop,returningtothesquare()methodcallontheseconditeration
Clickthe StepOverbuttononcetoexecutethefunctionwithoutsteppingthrougheachline
ClicktheStepOverbuttonfourmoretimestomovethroughtotheendoftheprogram
ThedebuggerwillautomaticallycloseandreturntotheregularCodeEditormode
Clickthereddotyouaddedinthemargintoremovethebreakpoint
TheStepOutbuttonisusedtoreturntothefunctioncallerwhenyouaresteppingthroughlinesofacalledfunction.
SettingbreakpointsInallbutthesmallestofprograms,steppingthrougheachlineisverytediouswhendebugging.Instead,youcanquicklyreachthepartyouwishtoexaminebysettingmultiplebreakpointstohaltexecutiononparticularlines.SettingoneormorebreakpointsisusefultohelpyouunderstandhowcertainC#codeconstructswork–suchasthenestedloopconstructshownhere:
Breakpoints
Typethiscodetocreatethreenestedloopsthateachincrementacountervariablewithineachloop,andatotalpassiterationcounterintheinnermostloopinti,j,k;intpass=0;
for(i=1;i<4;i++){for(j=1;j<4;j++){for(k=1;k<4;k++){pass++;
}}
}
Clickinthegraymarginagainsteachlinecontainingtheclosingbraceofeachlooptosetthreebreakpoints–areddotwillappearinthemarginandeachclosingbraceishighlightedtoindicatethebreakpointsareset
ClicktheStartbuttonandseetheapplicationruntothefirstbreakpointitmeets
ClickDebug,Windows,LocalstolaunchtheLocalswindowandnoticethecurrentvalueofeachvariable
Yellowarrowsindicatethecurrentposition.Clickonthereddottocancelabreakpoint.
WatchthevariablevalueschangeasyourepeatedlyclicktheStart(Continue)buttontomovetoeachsuccessivebreakpointuntilyoureachthethirdouterloopbreakpoint
RepeatedlyclickStepIntountilyoureachtheclosingbraceoftheMain()methodtoseethefinalvalues
Attheendoftheprogram,eachcountervariablehasbeenincrementedbeyondtheupperlimitsetintheforstatements,toexiteachloop,andtherehasbeenatotalof27iterations(3x3x3).
ClicktheStartbuttononcemoretoruntothefirstbreakpoint,thenclickDebug,Windows,ImmediatetolaunchtheImmediatewindow
IntheImmediatewindow,typei=3andhitEnter,thenusetheStepIntobuttontostepthrougheachlineofjustthefinalcompleteouterloop’snineiterations
TheLocalswindowshowsallvariablesincurrentscopeastheprogramproceeds.
AnycodeyoutypeintotheImmediatewindowisdynamicallyappliedtotheapplicationbeingdebugged,butdoesnotchangeitscode.
Catchingrun-timeerrorsWhenyouareabletopredictpotentialruntimeerrors,byconsideringalleventualities,youcanprovidecodetohandleeachExceptionclasserrorthatmayarise–byaddingatry-catchconstruct.Yourprogramcansupplyinformationtotheuserabouttheerror,shouldyouwishtodoso,thenproceednormally:
ErrorHandling
Addthisprogramcodetorequestuserinputoftwonumericvaluesforaddition,thendisplaytheirsumtotalConsole.Write(“PleaseEnterANumber:“);doublenum1=Convert.ToInt16(Console.ReadLine());
Console.Write(“NowEnterAnotherNumber:“);doublenum2=Convert.ToInt16(Console.ReadLine());
Console.WriteLine(“Total:“+(num1+num2));
PressStartorF5toruntheapplication,thenenteranysix-figureintegerandhitEnter
ThecompilerreportsanOverflowExceptionerror
ClicktheStopDebuggingbuttonsoyoucaneditthecode
AnInt16isa16-bitintegerwithintherange-32,768to+32,767–whereasanInt32isa32-bitintegerwithin-2,147,483,648to+2,147,483,647.
DragthemousetohighlightallstatementsinStep1,thenright-clickonthehighlightedareaandchooseInsertSnippet:,VisualC#,tryfromthecontextmenu
TheInsertSnippetfeatureprovideslotsofusefulpiecesofcodetopasteintotheCodeEditor–takesometimetoexploreitscontents.
Atry-catchconstructisaddedtothecode,enclosingthehighlightedstatementswithinthetryblock
Editthedefaultcatchblocktodisplayanerrormessagecatch(Exceptionerror){Console.WriteLine(error.Message);}
EachExceptionhasseveralmethodsandproperties.Forexample,useerror.GetType()toseethetypeofException.
Runtheapplication,thenenteranysix-figureintegerandhitEntertonowseeadefaultexplanatoryerrormessage
YoucanprovideyourownerrormessagestohandleaspecificExceptionbystatingitstypeinthecatch()parentheses:
Editthedefaultcatchblocktodisplayacustommessagecatch(OverflowException){Console.WriteLine(”\nMaximum:“+Int16.MaxValue);}
Runtheapplication,thenenteranysix-figureintegerandhitEntertonowseeacustomexplanatoryerrormessage
Youcanaddmultiplecatchblocksafterthetryblock,tohandledifferenttypesofException.
GettinghelpTheVisualStudioHelpsystemprovidesanextensivesourceofreferenceformanyprogramminglanguages.YoucanchoosetoinstallaHelpLibraryonyourcomputerfortheC#programminglanguagesoyoucaneasilyrefertoitatanytime:
OntheVisualStudioMenuBar,clickHelp,AddandRemoveHelpContenttoopentheHelpViewer
OntheManageContenttab,expandRecommendedDocumentationthenchoosetheAddlinkintheActioncolumnfortheVisualBasicandVisualC#library
WhenyourselectionisaddedtothePendingchangeslist,clicktheUpdatebuttontodownloadthatlibrary
TheHelpViewerallowsyoutodownloadHelplibrariesforofflineuse,checkforavailableupdates,andseekhelpfrominstalledHelplibraries.
HelplibrarydocumentationcanbesearchedforanswerstoyourC#codingquestions.Forexample,youmightwanttodiscoverbuilt-indatatypesavailableinC#programming:
OntheMenuBar,clickHelp,SetHelpPreference,LaunchinHelpViewertouseinstalledlibraries
Next,clickHelp,ViewHelptolaunchHelpViewer
Now,selecttheIndextabintheleft-handpane
Finally,enter“C#language,datatypes”intheHelpViewersearchbox,thenhitEntertoseetheresults
YoucanSetHelpPreferencetoLaunchinBrowserifyouwanttosearchonlinehelpwithoutinstallinglibraries,butlocalhelpisoftenmoreconvenient.
Summary• TheCodeEditorconstantlymonitorsyourcodetoprovidereal-timeerrordetection.
• Warningsarenotcriticalandareindicatedbyagreenwavyunderline–whereaserrorsarecriticalandareindicatedbyaredwavyunderline.
• Alightbulbiconbesidearedwavyunderlineindicatesthatalistofpotentialfixesisavailable.
• Typically,real-timeerrorsareerrorsofsyntax,andcompileerrorsareerrorsoflogic.
• WhenacompileerroroccursinDebugMode,executionstopsandtheExceptionAssistantoffersalistofpossiblefixes.
• InDebugModeyoucandiscoverthecurrentvalueofanyvariablesimplybyplacingthecursoroverthevariablename.
• Whendebuggingcode,theStepIntobuttonletsyouwalkthroughaprogramonelineatatime.
• TheStepOverbuttonletsyoubypassthelinesofacalledmethod,andtheStepOutbuttonletsyoureturntothelinewherethatmethodiscalled.
• Variablevaluescanbemonitoredasaprogramproceeds,usingtheWatchwindowortheLocalswindow.
• Breakpointshalttheexecutionofaprogramtoallowexaminationofthepartoftheprogramwheretheyareset.
• InDebugMode,codecanbedynamicallyappliedusingtheImmediatewindow.
• Runtimeerrorsoccurwhentheuseractionhasnotbeenanticipatedbytheprogrammer.
• Atry-catchblockcanbeusedtohandleanticipatedexceptions.
• TheHelplibrarysystemprovidesextensivereferencesourcesforbothoff-lineandonlineassistance.
9
Creatingobjects
Thischapterdemonstratesencapsulation,inheritance,andpolymorphism–thethreeprinciplesofC#ObjectOriented
Programming.
EncapsulatingdataCreatingmultipleobjectsInitializingclassmembersInheritingclasspropertiesCallingbaseconstructorsHidingbasemethodsDirectingmethodcallsProvidingcapabilityclassesEmployingpartialclassesSummary
EncapsulatingdataAclassisadatastructurethatcancontainbothvariablesandmethodsinasingleentity.Thesearecollectivelyknownasits“members”,andthevariablesarealsoknownasits“properties”.
Ifaclassisnotdeclaredasstaticitcanbeusedtocreate“instances”thatareassignedtoavariableforusebyotherclasses.
Accesstoclassmembersfromoutsidetheclassiscontrolledby“accessspecifiers”intheclassdeclaration.Typically,thesewilldenyaccesstothevariablemembers,butallowaccesstomethodsthatcanstoreandretrievedatafromthosevariablemembers.Thistechniqueof“datahiding”ensuresthatstoreddataissafelyencapsulatedwithintheclassvariablemembers,andisthefirstprincipleofObjectOrientedProgramming(OOP).
Aclassdeclarationcomprisesaclassaccessspecifier,theclasskeyword,andaprogrammer-specifiedname–adheringtotheusualC#namingconventions,butbeginninginuppercase.
Ifnotspecified,thedefaultaccessspecifierforaclassdeclarationisinternal,andthedefaultaccessspecifierforclassmembersisprivate.
Theclassdeclarationisfollowedbyapairofbracescontainingthevariableandmethoddeclarations,whichtypicallybeginwiththeirownaccessspecifier.So,classsyntaxlookslikethis:
access-specifierclassClassName{//Membervariableproperty.access-specifierdata-typevariable-name;
//Membermethod.access-specifierreturn-typemethod-name(parameter-list){statements
}}
Anaccessspecifiermaybeanyoneofthesekeywords:
• public–accessiblefromanyplacewheretheclassisvisible
• private–accessibleonlytoothermembersofthesameclass
• protected–accessibleonlytoothermembersofthesameclassandmembersofclassesderivedfromthatclass
• internal–accessibleonlytomembersofthesameassembly
Derivedclasses,whichusetheprotectedmemberaccessspecifier,areintroducedlater–seehere.
Anyreal-worldobjectcanbedefinedbyitsattributesandbyitsactions.Forexample,adoghasattributessuchasname,age,andcolor,plusactionsitcanperformsuchasbark.TheclassmechanisminC#providesawaytocreateavirtualdogobjectwithinaprogram,wherethevariablemembersofaclasscanrepresentitsattributesandthemethodsrepresentitsactions:
publicclassDog{//MEMBERVARIABLES...privatestringname;privateintage;privatestringcolor;
//MEMBERMETHODS...
//Setter&GetterMethods:publicvoidsetName(stringtag){
name=tag; //Storetheargumentvalue.}
publicstringgetName(){
returnname; //Retrievethestoredvalue.}
publicvoidsetAge(intyrs){age=yrs;}publicintgetAge(){returnage;}
publicvoidsetColor(stringcoat){color=coat;}publicstringgetColor(){returncolor;}
//OtherMethods:publicstringbark(){return“\nWoof,woof!\n”;}
}
Itisimportanttorecognizethataclassdeclarationonlydefinesadatastructure–inordertocreateanobjectyoumustdeclarean“instance”ofthatdatastructure,assignedtoavariable.Thisrequiresthenewkeywordandclassnamefollowedbyparentheses:
//Createaninstancenamed“fido”ofthe//programmer-definedDogdatastructure.Dogfido=newDog();
TheprincipleofencapsulationinC#programmingdescribesthegroupingtogetherofdataandfunctionalityinclassmembers–name,age,colorattributesandbarkactionintheDogclass.
Aprogramclasscannotperfectlyemulateareal-worldobject,butaimstoencapsulateallrelevantattributesandactions.
Thepublic“setter”and“getter”methodsassignvaluesto,andretrievevaluesfrom,theprivatevariablemembers.
Itisconventionaltobeginclassnameswithanuppercasecharacter,andobjectnameswithlowercase.
CreatingmultipleobjectsAprogramcaneasilycreatemultipleobjectssimplybydeclaringmultiplenewinstancesofaclass,andeachobjectcanhaveuniqueattributesbyassigningindividualvalueswithitssettermethods.
Itisoftenconvenienttocombinethesettermethodsintoasinglemethodthatacceptsargumentsforeachprivatevariable.Thismeansthatallvaluescanbeassignedwithasinglestatementintheprogram,butthemethodwillcontainmultiplestatements.
InC#classdeclarations,thepublic“setter”methods,whichassigndatatoprivatevariablemembers,andpublic“getter”methods,whichretrievedatafromprivatevariablemembers,areoftennamedasthevariabletheyaddress–butwiththefirstlettermadeuppercaseandprefixedby“set”or“get”respectively.Forexample,methodstoaccessanagevariablemaybesetAge()andgetAge().
Parametersmayalsobenamedasthevariabletheyaddress.Thecodecandifferentiatebetweentheparameterandlike-namedvariablememberbydot-prefixingthistothevariablename:
Objects
AfterthedefaultProgramclass,declareaclassnamed“Dog”withthreevariablememberspublicclassDog{privatestringname,color;privateintage;
//Methodstobeinsertedhere(Steps2-4).}
Next,insertasettermethodforallvariablememberspublicvoidsetValues(stringname,intage,stringcolor){this.name=name;this.age=age;this.color=color;
}
Now,insertgettermethodsforeachvariablememberpublicstringgetName(){returnname;}publicintgetAge(){returnage;}publicstringgetColor(){returncolor;}
Then,insertanothermiscellaneousmethodpublicstringbark(){return“\nWoof,woof!\n”;}
Inthesettermethod,thethisprefixednamesreferencetheclassvariablemembers,andthosewithoutprefixreferencetheparameters.Noprefixisneededtoreferencetheclassvariablemembers.
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateaninstanceoftheDogclassDogfido=newDog();
Next,callthenewinstanceobject’ssettermethodtoinitializeallitsvariablemembersfido.setValues(“Fido”,3,“Brown”);
Now,retrieveallpropertiesofthenewobjectstringtagF=String.Format(“{0}isa{1}yearold{2}dog”,
fido.getName(),fido.getAge(),fido.getColor()
};
DisplayallpropertiesandcallthemiscellaneousmethodConsole.WriteLine(tagF+fido.bark());
Now,createanotherinstanceoftheDogclassDoglucy=newDog();lucy.setValues(“Lucy”,2,“Gray”);
Next,retrieveallpropertiesofthisnewobjectstringtagL=String.Format(“{0}isa{1}yearold{2}dog”,
lucy.getName(),lucy.getAge(),lucy.getColor()
};
DisplayallpropertiesandcallthemiscellaneousmethodConsole.WriteLine(tagL+lucy.bark());Console.ReadKey();
PressStartorF5toseeeachobject’sproperties
NoticeherehowtheString.Format()methodiscodedusingnewlinestoclearlybuildastringvalueforoutput.
InitializingclassmembersClassvariablememberscanbeinitializedbyaspecial“constructor”methodthatiscalledwheneveraninstanceoftheclassiscreated–allowingyoutospecifydefaultvaluesforclassvariablemembers.
Theconstructormethodisalwaysnamedexactlyastheclassnameandcancontainstatementstoinitializeclassvariablemembers.Forexample,publicclassCathasapublicCat()constructor.
Whenallclassvariableshavebeeninitializedbytheclassconstructormethod,anyinstanceobjectofthatclasswillimmediatelyhavethoseinitialpropertyvalues.Individualsettermethodscanusefullyadjusttheclassvariablevaluesasneeded:
Constructor
AfterthedefaultProgramclass,declareaclassnamed“Cat”withthreevariablememberspublicclassCat{privatestringname,color;privateintage;
//Methodstobeinsertedhere(Steps2-5).}
Next,insertaclassconstructormethodtosetdefaultvaluesforallitsvariablememberspublicCat(){name=“Tigger”;age=3;color=“Brown”;
}
Now,insertsettermethodsforeachvariablememberpublicvoidsetName(stringname){this.name=name;}publicvoidsetAge(intage){this.age=age;}publicvoidsetColor(stringcolor){this.color=color;}
Then,insertgettermethodsforeachvariablememberpublicstringgetName(){returnname;}publicintgetAge(){returnage;}publicstringgetColor(){returncolor;}
Lastly,insertanothermiscellaneousclassmethodpublicstringcry(){return“\nMeow,meow!\n”;}
Youcannotspecifyaconstructortobeprivateasitmustbeaccessibleinordertocreateinstanceobjectsinotherclasses.
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateaninstanceoftheCatclassCattigger=newCat();
Now,retrieveall(default)propertiesofthenewobjectstringtagT=String.Format(“{0}isa{1}yearold{2}cat”,
tigger.getName(),tigger.getAge(),tigger.getColor()
};
DisplayallpropertiesandcallthemiscellaneousmethodConsole.WriteLine(tagT+tigger.cry());
Now,createanotherinstanceoftheCatclassandseteachpropertywithnewvaluesCatsmokey=newCat();
smokey.setName(“Smokey”);smokey.setAge(2);smokey.setColor(“Gray”);
Next,retrieveall(adjusted)propertiesofthisnewobjectstringtagS=String.Format(“{0}isa{1}yearold{2}cat”,
smokey.getName(),smokey.getAge(),smokey.getColor()
};
DisplayallpropertiesandcallthemiscellaneousmethodConsole.WriteLine(tagS+smokey.cry());Console.ReadKey();
PressStartorF5toruntheapplicationandseethepropertiesofeachobjectinstanceandmethodcalled
Objectinstancescannotbecreatedfromstaticclasses,butyoucansupplyaconstructormethodinstaticclasses.
Youcanalsospecifyparameterstoaconstructormethodinordertoallowargumentvaluestobepassedinwhenanewinstanceobjectiscreated.
InheritingclasspropertiesAC#classcanbecreatedasabrandnewclass,likethoseinpreviousexamples,orcanbe“derived”fromanexistingclass.Importantly,aderivedclassinheritsmembersoftheparent(base)classfromwhichitisderived–inadditiontoitsownmembers.
Theabilitytoinheritmembersfromabaseclassallowsderivedclassestobecreatedthatsharecertaincommonproperties,whichhavebeendefinedinthebaseclass.Forexample,a“Polygon”baseclassmaydefinewidthandheightpropertiesthatarecommontoallpolygons.Classesof“Rectangle”andTriangle”couldbederivedfromthePolygonclass–inheritingwidthandheightproperties,inadditiontotheirownmembersdefiningtheiruniquefeatures.
ThevirtueofinheritanceisextremelypowerfulandisthesecondprincipleofObjectOrientedProgramming(OOP).
Aderivedclassdeclarationaddsacolon:afteritsclassname,followedbythenameoftheclassfromwhichitderives:
Inheritance
AfterthedefaultProgramclass,declareabaseclassnamed“Polygon”,containingtwovariablemembersandonesettermethodmemberpublicclassPolygon{protectedintwidth,height;
publicvoidsetValues(intwidth,intheight){this.width=width;this.height=height;
}
}
Next,defineaclassthatderivesfromthebaseclass,inheritingmembersandaddingamethodpublicclassRectangle:Polygon{publicintarea(){return(width*height);}
}
Now,defineanotherclassthatderivesfromthebaseclass,inheritingmembersandaddingasimilarmethodtothatintheprevioussteppublicclassTriangle:Polygon{publicintarea(){return((width*height)/2);}
}
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateaninstanceobjectfromeachderivedclassRectanglerect=newRectangle();Trianglecone=newTriangle();
Calltheinheritedsettermethodofeachderivedclasstoinitializealltheinheritedvariablemembersrect.setValues(4,5);cone.setValues(4,5);
Finally,calltheaddedmethodineachderivedclasstodisplaytheircomputedvaluesConsole.WriteLine(“RectangleArea:“+rect.area());Console.WriteLine(“\nTriangleArea:“+cone.area());Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfrominheritedvariables
Themethodsaddedtoeachderivedclasscanbenamedalike,astheyonlyexistwithinthescopeoftheirrespectiveclass.
The:operatorisusedheretocreatederivedclasses,andisequivalenttotheextendskeywordinotherprogramminglanguages–suchasJava.
Noticethatthesettermethodandvariablesarenotdefinedinthederivedclasses,astheyareinheritedfromthebaseclass.
CallingbaseconstructorsAlthoughderivedclassesinheritthemembersoftheirparentbaseclass,theydonotinherititsconstructormethod.Nonetheless,aconstructormethodofthebaseclassisalwayscalledwhenanewobjectofaderivedclassiscreated.Thecalltothebaseclassconstructormethodismadeinadditiontothecalltotheconstructormethodofthederivedclass.
Thedefaultconstructormethodofabaseclasshasnoparameters–butthebaseclassmayalsohaveoneormore“overloaded”constructormethodswhichdohaveparameters.
Ifyouprefertocallanoverloadedconstructorofthebaseclasswhenanewobjectofaderivedclassiscreated,youcancreateamatchingoverloadedconstructorinthederivedclass–havingthesamenumberandtypeofarguments.Thematchingderivedclassconstructormustthenexplicitlycalltheoverloadedbaseclassconstructorusingthebasekeyword.Thisisappendedtothederivedclassconstructordeclarationaftera:coloncharacter.
Anoverloadedmethodisonethathasthesamenameasanothermethodbutdifferentparameters.
Whenanewobjectofaderivedclassiscreated,argumentvaluescanbepassedtoanoverloadedderivedclassconstructor,andalsoonwardstoitsmatchingoverloadedbaseclassconstructorinparenthesesfollowingthebasekeyword:
Base
AfterthedefaultProgramclass,declareabaseclassnamed“Parent”,containingadefaultconstructormethodpublicclassParent{publicParent(){Console.WriteLine(“ParentCalled”);
}
//Overloadedconstructortobeinsertedhere(Step2).}
Next,insertanoverloadedconstructormethodintothebaseclassthatrequiresasingle
integerargumentpublicParent(intnum){
Console.WriteLine(“Parent+Called:”+num);}
Afterthebaseclass,addaderivedclasscontainingadefaultconstructormethodpublicclassDaughter:Parent{publicDaughter(){Console.WriteLine(“\tDaughterCalled\n”);}
}
Son–Parent–Daughter
Next,addanotherderivedclass,containingadefaultconstructormethodpublicclassSon:Parent{publicSon(){Console.WriteLine(“\tSonCalled\n”);}
//Overloadedconstructortobeinsertedhere(Step5).}
Now,insertanoverloadedconstructormethodintothederivedclass,whichrequiresasingleintegerargumentpublicSon(intnum):base(num){Console.WriteLine(“\tSon+Called:”+num);
}
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateinstancesofthederivedclassesDaughteranna=newDaughter();Sonbrad=newSon();Soncarl=newSon(100);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfrombaseandderivedclassconstructors
Thedefaultbaseconstructormethodwillbecalledimplicitlyunlessthebasekeywordisusedtocallexplicitly.
Here,theargumentvalueispassedtothederivedclassandbaseclass.
HidingbasemethodsAmethodcanbedeclaredinaderivedclassto“hide”asimilarmethodinthebaseclass–ifbothmethoddeclarationshavematchingname,arguments,andreturntype.
Creationofamatchingmethodinaderivedclasseffectivelyhidesthebaseclassmethod,asitgenerallybecomesinaccessible.Toindicatethathidingisintentional,ratherthanaccidental,thehidingmethoddeclarationshouldincludethenewkeyword.
Baseclassmethodscanbecalledexplicitlyfromwithinnon-staticclassesbyprefixingtheirmethodnamewiththebasekeyword.Alternatively,asaderivedclassisaspecializationofitsbaseclass,baseclassmethodscanbecalledexplicitlyusinganexplicitcast:
Hide
AfterthedefaultProgramclass,declareabaseclassnamed“Man”,containingasimplemethodwithoutparametersplusanoverloadedmethodwithasingleparameterpublicclassMan{publicvoidspeak(){Console.Write(“Hello:”);
}
publicvoidspeak(stringmessage){Console.WriteLine(message+“!\n”);
}}
Afterthebaseclass,addaderivedclasscontainingamethodtointentionallyhidetheoverloadedmethodofthesamenameandparametersinthebaseclasspublicclassHombre:Man{publicnewvoidspeak(stringmessage){//Statementtobeinsertedhere(Step3).Console.WriteLine(message);}
}
Next,insertastatementinthederivedclasstoexplicitlycallthesimplemethodinthebaseclassbase.speak();
Aderivedclassmethodnameandparameterlistmustmatchthatinitsbaseclasstooverrideit.
TurnyourattentiontotheMain()methodinthedefaultProgramclass,andcreateaninstanceofthebaseclassManhenry=newMan();
Next,createaninstanceofthederivedclassHombreenrique=newHombre();
HenryandEnrique
Addacalltothesimplemethodinheritedbytheinstancefromthebaseclasshenry.speak();
Now,addacalltotheoverloadedmethodinheritedfromthebaseclasshenry.speak(“It’sabeautifulevening”);
Then,addacalltothehidingmethodinthederivedclass–thatwillalsoexplicitlycallthesimplemethodinthebaseclassenrique.speak(“Hola...”);
Finally,addastatementusinganexplicitcast–toexplicitlycalltheoverloadedmethodinthebaseclass((Man)enrique).speak(“Esunatardehermosa”);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfrombaseclassmethodsandhidingmethod
ThebasekeywordcannotbeusedintheMain()method,asthatisastaticmethod.
DirectingmethodcallsThethreecornerstonesofObjectOrientedProgramming(OOP)areencapsulation,inheritance,andpolymorphism.Previousexampleshavedemonstratedencapsulationofdatawithinaclass,andinheritanceofbaseclassmembersbyderivedclasses.Thetermpolymorphism(fromGreek,meaning“manyforms”)describestheabilitytoassignadifferentmeaning,orpurpose,toanentityaccordingtoitscontext.C#overloadedoperatorscanbedescribedaspolymorphic.Forexample,the+symbolrepresentstheadditionorconcatenationoperator–accordingtoitscontext.C#classmethodscanalsobepolymorphic.Methoddeclarationsinabaseclasscanincludethevirtualkeywordtoallowthatmethodtobeoverriddeninderivedclasses.Similarly,methoddefinitionsinaderivedclasscanincludetheoverridekeywordtodenoteitwillbeoverridingavirtualbaseclassmethod.Inthisway,derivedclassmethodscanprovidetheirownversionofabaseclassmethod.Thegreatadvantageofpolymorphismwithmultiplederivedclassobjectsisthatcallstomethodsofthesamenamearedirectedtotheappropriateoverridingmethod.Thiscanallowinconsistencies,however–thisexampleseemstoimplythatchickenscanfly!
Override
AfterthedefaultProgramclass,declareabaseclassnamed“Bird”,containingtwomethodsthatallowoverridingpublicclassBird{publicvirtualvoidtalk(){Console.WriteLine(“ABirdTalks...”);}
publicvirtualvoidfly(){Console.WriteLine(“ABirdFlies...\n”);}
}
Afterthebaseclass,addaderivedclasscontainingtwomethodsthatwilloverridethebaseclassmethodspublicclassPigeon:Bird{publicoverridevoidtalk()
{Console.WriteLine(“PigeonSays:Coo!Coo!”);}
publicoverridevoidfly(){Console.WriteLine(“APigeonFliesAway...”);base.fly();
}}
Here,thefly()methodineachderivedclassalsocallsthebaseclassfly()methoddirectly.
Next,addanotherderivedclasscontainingtwomethodsthatwillalsooverridethebaseclassmethodspublicclassChicken:Bird{publicoverridevoidtalk(){Console.WriteLine(“ChickenSays:Cluck!Cluck!”);}
publicoverridevoidfly(){Console.WriteLine(“I’mAChicken-ICan’tFly”);base.fly();
}}
TurnyourattentiontothedefaultProgramclassandaddamethodtocallbothoverridingmethodsstaticvoiddescribe(Birdobj){
obj.talk();obj.fly();
}
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateinstancesofeachnon-baseclassPigeonjoey=newPigeon();Chickenlola=newChicken();
Finally,addstatementstocallappropriatemethodsdescribe(joey);describe(lola);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfromtheoverridingmethodsofderivedclasses
Youmustusethebasekeywordprefixtodirectlycallabaseclassmethodfromaderivedclass.
EachinstanceobjectispassedasanargumentforC#todeterminetheappropriateoverridingmethodtoexecute.
Polymorphisminprogrammingisoftencalled“oneinterface,multiplefunctions”.
ProvidingcapabilityclassesClasseswhosesolepurposeistoallowotherclassestobederivedfromthemareknownas“capabilityclasses”–theyprovidecapabilitiestothederivedclasses.Capabilityclassesgenerallycontainnodata,butmerelydeclareanumberofmethodsthatcanbeoverriddenintheirderivedclasses.
Acapabilityclassanditsmethodscanallbedeclaredusingtheabstractkeywordtodenotethattheycanonlybeimplementedinderivedclasses.Inthiscase,themethodsignatureisfollowedbyasemicolon,ratherthanamethodblockcontainingstatements.Methoddefinitionsinderivedclassescanthenincludetheoverridekeywordtoimplementthecapabilityclassmethods.
Youcannotcreateaninstanceofanabstractbaseclass.
Addingthesealedkeywordtoaclassdeclarationisasafeguardwhichpreventsthatclassbeingusedasabaseclass.Understandably,anabstractcapabilityclasscannotbesealed.
Thefollowingexamplebuildsuponthepreviousexampletodemonstratehowthe“Bird”classcanbebetterwrittenasacapabilityclass.Thisnowpreventsthebaseclassmethodsbeingcalleddirectly,toavoidinconsistencies:
Capability
AfterthedefaultProgramclass,defineabasecapabilityclassnamed“Bird”,containingtwomethodspublicabstractclassBird{publicabstractvoidtalk();
publicabstractvoidfly();}
AddaderivedclasscontainingtwomethodsthatwilloverridethebaseclassmethodspublicsealedclassPigeon:Bird{publicoverridevoidtalk(){Console.WriteLine(“PigeonSays:Coo!Coo!”);}
publicoverridevoidfly(){Console.WriteLine(“APigeonFliesAway...”);}
}
Next,addanotherclasswhichalsocontainstwomethodsthatwilloverridethebaseclassmethodspublicsealedclassChicken:Bird{publicoverridevoidtalk(){Console.WriteLine(“ChickenSays:Cluck!Cluck!”);}
publicoverridevoidfly(){Console.WriteLine(“I’mAChicken-ICan’tFly”);}
}
Chicken(Bird)
Pigeon(Bird)
Next,addanotherclasscontainingasinglemethodthatacceptsanobjectargumentpublicsealedclassCaller{publicvoiddescribe(Birdobj){obj.talk();obj.fly();
}}
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateinstancesofeachnon-baseclassPigeonjoey=newPigeon();Chickenlola=newChicken();Callercall=newCaller();
Finally,addstatementstocallappropriatemethodsbypassinganobjectasanargumentcall.describe(joey);call.describe(lola);Console.ReadKey();
PressStartorF5toruntheapplicationandseetheputfromtheoverridingmethodsofderivedclasses
EachinstanceobjectispassedasanargumentforC#todeterminetheappropriateoverridingmethodtoexecute.
EmployingpartialclassesThesourcecodeforeachexamplelistedinthisbookisgenerallycontainedinasingle.csfile,aseachoneisjustasimpleprogram.Whenworkingonlargerprojectsitisoftendesirabletospreadthesourcecodeoverseparatefilestoallowmultipleprogrammerstoworkontheprojectatthesametime.VisualStudioallowsyoutoeasilyaddoneormorecodefilesinwhichtowriteclasses.
Ifanypartisdeclaredabstract,thewholeclasswillbeabstract,andifanypartisdeclaredsealed,thewholeclasswillbesealed.
Classdefinitionscanalsobespreadacrossseveralfilesbyincludingthepartialkeywordineachseparatepartofthedefinition.Providingallpartshavethesamelevelofaccessibility,theC#compilerwillcombineallpartsintoasingledefinition:
Parts
StartanewConsoleApplication,thennametheprojectandConsole.Titleas“Parts”
FromtheVisualStudiomenu,selectProject,AddClasstolaunchthe“AddNewItem”dialogbox
Editthenamefieldtothenameoftheclasstobeaddedthere–inthiscaseit’stobeaclassnamed“Sailboat”
ClicktheAddbuttontoaddthenewfiletoyourproject
Next,selectView,SolutionExplorerandclickonSailboat.cstoopenthatfileinCodeEditor
Alternatively,youcanright-clickontheprojectnameinSolutionExplorerandchooseAdd,NewItemtolaunchthisdialogbox.
EdittheaddedfiletoprovideaclassconstructorpartpublicpartialclassSailboat{privatestringmake;privatestringmodel;
publicSailboat(stringmake,stringmodel){this.make=make;this.model=model;
}}
LaserSailboat(Boat)
Now,inSolutionExplorer,clickonProgram.cstoopenthatfileinCodeEditor
AfterthedefaultProgramclassaddaclassmethodpartpublicpartialclassSailboat{publicvoiddescribe(){Console.WriteLine(“Sailboat:{0}{1}”,make,model);
}}
TurnyourattentiontotheMain()methodinthedefaultProgramclassandcreateaninstanceobjectSailboatboat=newSailboat(“Laser”,“Classic”);
Finally,addastatementtocalltheaddedclassmethodboat.describe();Console.ReadKey();
PressStartorF5toruntheapplicationandseetheoutputfromtheclasspartsspreadovertwofiles
Noticehowthestringsaresubstitutedforoutputinthisexample.
Partialclassesarepartofthesamenamespace–hereitis“Parts”.
Summary• Encapsulation,inheritance,andpolymorphismarethethreecornerstonesofObjectOriented
Programming.
• AC#classisadatastructurethatcancontainbothvariablemembersandmethodmembers.
• Accesstoclassmembersiscontrolledbyaccessspecifiers.
• Aninstanceobjectofaclassiscreatedusingthenewkeywordfollowedbytheclassnameandparentheses.
• Typically,publicsetterandgettermethodsprovideaccesstoprivatevariablestoensurestoreddataissafelyencapsulated.
• Parameterscanbenamedasthevariabletheyaddress,andthethiskeywordprefixcanbeusedtodifferentiatebetweenthem.
• Theconstructormethodofaclassisnamedastheclassnameandiscalledeachtimeaninstanceofthatclassiscreated.
• Derivedclassesinheritmembersofthebaseparentclassfromwhichtheyarederived.
• Aderivedclassdeclarationaddsacolonaftertheclassname,followedbythenameoftheclassfromwhichitderives.
• Anoverloadedconstructorofabaseclasscanbecalledusingthebasekeywordinaderivedclassdeclaration.
• Aderivedclasscanincludeanewmethodtohideamethodinitsparentclassifname,arguments,andreturntypematch.
• Baseclassmethodscanbecalledexplicitlyfromaderivedclassbyprefixingthemethodnamewiththebasekeyword.
• Thevirtualandoverridekeywordscanbeusedtoallowbaseclassmethodstobeoverriddenbyderivedclassmethods.
• Capabilityclassescanincludetheabstractkeywordtodenotetheirmethodscanonlybeimplementedinderivedclasses.
• Addingthesealedkeywordtoaclassdeclarationisasafeguardwhichpreventsthatclassbeingusedasabaseclass.
• Classdefinitionscanbespreadacrossseveralfilesbyincludingthepartialkeywordineachpartofthedefinition.
10
Controllingevents
ThischapterdemonstrateshowaC#programcanrecognizeandrespondtoeventsthatoccurinagraphicalapplication.
StartingaFormsprojectAddingvisualcontrolsWritingfunctionalcodeGatheringtextentriesTickingoptionboxesShowingusermessagesCallingsystemdialogsCreatingapplicationmenusMakingmenusworkImportingaudioresourcesSummary
StartingaFormsprojectVisualStudioprovidesaWindowsFormsApplicationtemplatethatallowsyoutoeasilycreateaC#programwhichprovidesaGraphicalUserInterface(GUI)tointeractwiththeuser:
FirstGUI
OntheMenuBar,clickFile,New,Project,orpresstheCtrl+Shift+Nkeys,toopentheNewProjectdialogbox
IntheNewProjectdialog,expandInstalled,Templates,VisualC#,thenselecttheWindowsFormsApplication
EnteraprojectnameofyourchoiceintheNamefield,thenclickontheOKbuttontocreatethenewproject–inthiscasetheprojectnamewillbe“FirstGUI”
WaitwhileVisualStudiocreatesyournewprojectandloadsitintotheIDE,thenseeaFormDesignerwindowappeardisplayingadefaultemptyForm
SelecttheView,SolutionExplorermenutoopenaSolutionExplorerwindowandseeallfilesinyourproject
WindowsGUIapplicationsprovideinteractivecontrolsthatproduce“events”inresponsetouseractions,andyourprogramcanrespondtothoseactions.Thisisknownasevent-drivenprogramming.
Now,selecttheView,PropertiesmenutoopenaPropertieswindowtorevealallpropertiesofyourForm
TheFormDesigneriswhereyoucreatevisualinterfacesforyourapplications,andthePropertieswindowcontainsdetailsoftheitemthatiscurrentlyselectedintheFormDesignerwindow.
TheVisualStudioIDEhasnowgatheredalltheresourcesneededtobuildadefaultWindowsapplication–clicktheStartbuttononthetoolbartolaunchthisapplication
Theapplicationsimplycreatesabasicwindow–youcanmoveit,minimizeit,maximizeit,resizeit,andquittheapplicationbyclosingit.Itmaynotdomuch,butyouhavealreadycreatedarealWindowsGUIapp!
Alternatively,youcanrunapplicationsusingtheDebug,StartDebuggingmenuoptionsorpressF5.
AddingvisualcontrolsTheToolboxintheVisualStudioIDEcontainsawiderangeofvisualcontrols,whicharethebuildingblocksofyourapplications.Usingtheprojectcreatedhere,followthesestepstostartusingtheToolboxnow:
FirstGUI
PlacethecursorovertheverticalToolboxtabattheleftedgeoftheIDEwindow,orclickView,ToolboxontheMenuBar,todisplaytheToolboxcontents.Thevisualcontrolsarecontainedundervariouscategoryheadingsbesidean expansionarrow
ClickontheexpansionarrowbesidetheCommonControlscategoryheadingtoexpandthelistofmostcommonlyusedvisualcontrols.Usefully,eachcontrolnameappearsbesideanicondepictingthatcontrolasareminder.Youcanclickonthecategoryheadingagaintocollapsethelist,thenexpandtheothercategoriestoexploretherangeofcontrolsavailabletobuildyourapplicationinterfaces
AnypinnedWindowintheIDEcanbedraggedfromitsusuallocationtoanypositionyouprefer.Dragbacktotheinitiallocationtore-dockit.
TheToolboxwillautomaticallyhidewhenyouclickonanotherpartoftheIDE,butitcanbefixedinplacesoitwillneverhide,usingthe PinbuttonontheToolboxbar.
ClickanddragtheButtonitemfromtheCommonControlscategoryintheToolboxontotheFormintheDesignerwindow,ordouble-clicktheButtonitem,toaddaButtoncontroltotheForm
AButtonisoneofthemostusefulinterfacecontrols–yourprogramdetermineswhathappenswhentheuserclicksit.
TheButtoncontrolappearsontheFormsurroundedby“handles”whichcanbedraggedtoresizethebutton’swidthandheight.
Clickthe StartbuttontoruntheapplicationandseetheButtoncontrolappearinitsinitialdefaultstate
Next,movethepointerovertheButtoncontroltoseeitsappearancechangetoits“MouseHover”state
Now,clickandholddowntheButtoncontroltoseeitsappearancechangetoits“MouseDown”state
Finally,releasetheButtoncontroltoseeitsappearancechangetoits“MouseUp”state
ThisButtoncontrolperformsnofunctionwhenit’sclicked–untilyouaddsomecode.
EachchangeofappearanceisWindows’defaultresponsetoaneventthatoccursontheButton
control,butyourC#programcanprovideitsownresponsetothese,andmanymore,controlevents:
SelecttheButtoncontrolthenopenitsPropertieswindow
ClicktheEventsbuttonandscrolldowntoseeallpossibleButtonevents
EachcontrolcanbegivenamoremeaningfulnameinthePropertieswindow,butforsimplicity,thedefaultnamesareusedbytheexamplesinthisbook.
WritingfunctionalcodeTheVisualStudioIDEautomaticallygeneratescodeinthebackground,toincorporatethevisualcontrolsyouaddtoyourprograminterface.Additionalcodecanbeaddedmanuallytothe“code-behind”pageusingtheIDE’sintegralCodeEditor,todeterminehowyourprogramshouldrespondtointerfaceevents:
UsethetabstoswitchbetweentheCodeEditorandFormDesigner.
Usingtheprojectcreatedhere,followthesestepstoaddyourownresponsestouseractionswhichproduceevents:
FirstGUI
SelecttheButtoncontrolnamedbutton1,thenopenitsPropertieswindowandclicktheEventsbutton
Double-clickontheMouseHoveritemtoopenaForm1.cscode-behindpageinCodeEditoratageneratedevent-handlermethod
Next,insertthisstatementwithinthegeneratedmethod–tochangetheButton’sbackgroundcolorinresponsetoaMouseHovereventbutton1.BackColor=Color.Fuchsia;
Similarly,double-clickontheMouseDownitemandinsertthisstatementwithinanother
generatedmethod–tochangetheButton’sbackgroundcolorinresponsetoaMouseDowneventbutton1.BackColor=Color.Lime;
Likewise,double-clickontheMouseUpitemandinsertthisstatementwithinafurthergeneratedmethod–tochangetheButton’sbackgroundcolorinresponsetoaMouseUpeventbutton1.BackColor=Color.Aqua;
TheColorclassprovideslotsofstandardcolorproperties–typeColorthenaperiodanduseIntelliSensetoseethem.
ThelinesofcodeinthisexamplearetobeinsertedintoeachindividualeventhandlermethodthatisautomaticallygeneratedbyVisualStudio.
Now,clicktheForm1.cs[Design]tabtoreturntotheFormDesignerwindow
Double-clickontheButtoncontrolontheFormtoopentheForm1.cscode-behindpageinCodeEditoratyetanothergeneratedevent-handlermethod
Finally,insertthisstatementwithinthegeneratedmethod–toopenamessageboxinresponsetoaClickeventMessageBox.Show(“C#Programmingineasysteps”);
Runtheapplication,thenclickthebuttontoseetheMouseHover,MouseDown,andClickeventresponses
PushtheOKbuttontoclosethemessageboxandseetheMouseUpeventresponse
YoucanusetheViewmenuontheMenuBartoopentheCodeEditor,FormDesigner,oranyotherwindowyourequireatanytime.
YoucanseemanymoreusesfortheMessageBoxclasshere.
MostWindowssoftwareworksbyrespondingtoevents.Forexample,whenyoupressakey,aKeyPresseventcancallitsevent-handlertorespondtothatevent.
GatheringtextentriesATextBoxcontrolcanbeaddedtoaForminaWindowsFormsApplicationtoallowtheusertoenterinput.ThecurrentvaluewithinaTextBoxcanbeassignedtoavariable,typicallyinresponsetoaButtonClickevent,foruseinsidetheprogramcode.
ALabelcontrolisgenerallyusedtodisplaynon-dynamictext.
AnewvaluecanbeassignedtoaTextBoxasoutputtotheuser,buttheusercanmodifythisvalue.Alternatively,outputcanbeassignedtoaLabelcontrol,whichtheusercannotmodify:
Entry
StartanewWindowsFormsApplication,thenaddaTextBox,aButton,andtwoLabelcontrols
SelecttheFormitself,theninthePropertieswindowmodifyitsTextvalueandheight
Next,modifytheTextpropertyvaluesoftheButtoncontrolandLabelcontrolssotheylooklikethis:
Now,double-clicktheButtoncontroltoopentheCodeEditoratageneratedClickevent-handler
AttheverybeginningoftheForm1classblock,addavariablewithsetterandgettermethodsprivateintnum;publicvoidsetNum(intnum){this.num=num;}publicintgetNum(){returnnum;}
IntheLayoutpropertycategory,youmustsetAutoSizetoFalsebeforeyoucanadjusttheWidthandHeightvaluesintheSizepropertycategory.
IntheForm1()constructormethodblock,insertstatementstoinitializethevariablewitharandomvalueRandomrnd=newRandom();setNum(rnd.Next(1,21));
Then,addamethodtocomparetwoargumentsandsetaLabelcontrol’sTextpropertywithanappropriatemessagepublicvoidrate(intguess,intnum){if(guess<num)label2.text=“TooLow!”;elseif(guess>num)label2.text=“TooHigh!”;elselabel2.text=“***Correct***”;
}
Finally,insertstatementswithintheButtonClickevent-handlertocompareuserinputagainsttherandomvalueintguess=Convert.ToInt16(textBox1.text);rate(guess,getNum());
PressStartorF5toruntheapplicationandenterinputtoseetheappropriateoutputmessages
IfyouspecifyminimumandmaximumargumentstotheNext()method,itwillreturnarandomintegerbetweenthespecifiedminimumandmaximum-1–sospecifying21willallowamaximumof20.
ThecontentofaTextBoxcontrolisastringvalue–soitmustbeconvertedtoanumericdatatypefornumericcomparison.
TickingoptionboxesACheckBoxcontrolisasmallboxwithacaption.Itletstheuserselectthecaptionchoicebyclickingonthebox,andacheckmarkappearsintheboxtoindicateithasbeenchosen.Clickingtheboxoncemoredeselectsthechoiceandunchecksthebox.CheckBoxcontrolsareidealtopresentasetofchoicesfromwhichtheusercanselectnone,one,ormorethanonechoice.
ARadioButtoncontrolislikeaCheckBox,butwithonecrucialdifference–theusercancheckonlyonechoiceinthegroup.CheckingaRadioButtonautomaticallyunchecksanyothers.RadioButtoncontrolsareidealtopresentasetofchoicesfromwhichtheusercanselectonlyonechoice.
SetoneRadioButtoncontroltoCheckedtospecifyadefaultoption.
SelectedCheckBoxandRadioButtonitemscanusefullybeaddedtothecollectiondisplayedinaListBoxcontrol:
Option
StartanewWindowsFormsApplication,thenaddRadioButton,CheckBox,ListBox,Button,andLabelcontrolstotheForm
ModifytheTextpropertyvaluesofthecontrolstolooklikethis:
Now,double-clickthe“ShowSelection”ButtoncontroltoopentheCodeEditoratitsgeneratedClickevent-handler
ThenameoftheListBoxcontrolthatappearsintheFormDesignerwillnotbedisplayedwhentheapplicationruns.
IntheForm1()constructormethodblock,insertastatementtospecifyadefaultoptionradioButton1.Checked=true;
Next,insertastatementwithinthe“ShowSelection”ButtonClickevent-handlertoemptyanylisteditemslistBox1.Items.Clear();
Insertstatementswithinthe“ShowSelection”ButtonClickevent-handlertoaddselectedoptionstothelistif(radioButton1.Checked)listBox1.Items.Add(radioButton1.Text);
if(radioButton2.Checked)listBox1.Items.Add(radioButton2.Text);
if(checkBox1.Checked)listBox1.Items.Add(checkBox1.Text);
if(checkBox2.Checked)listBox1.Items.Add(checkBox2.Text);
Now,double-clickthe“Clear”ButtoncontroltoopentheCodeEditoratitsgeneratedClickevent-handler
Insertstatementswithinthe“Clear”ButtonClickevent-handlertoresetalltheoptionslistBox1.Items.Clear();radioButton1.Checked=true;checkBox1.Checked=false;checkBox2.Checked=false;
PressStartorF5toruntheapplicationandselectoptionstoseethemappearinthelist–thenhitClear
TheListBoxcontrolhasanItemspropertythatprovidesmethodstoaddorremovelistitemsfromacollection.
ShowingusermessagesThefeaturesofaMessageBoxdialogcanbedeterminedbyaddingthreefurtherargumentsafterthemessagestringwithinitsShow()method.Thesecanspecifyacaption,whichbuttonsthedialogwilldisplay,andwhichgraphiciconwillappearonthedialog.
MessageBoxButtonsconstants
AbortRetryIgnore
OK
OKCancel
RetryCancel
YesNo
YesNoCancel
ThedialogbuttoncombinationscanbespecifiedusingtheMessageBoxButtonsconstantvalueslistedinthistable.Forexample,tohavethedialogdisplayYes,No,andCancelbuttons,specifytheMessageBoxButtons.YesNoCancelconstant.
AMessageBoxis“modal”–theusermustdealwithitsdialogmessagebeforetheprogramcanproceed.
MessageBoxIcon constants
ErrorHandStop
Question
ExclamationWarning
AsteriskInformation
None
ThedialogiconcanbespecifiedusingtheMessageBoxIconconstantvalueslistedinthistable.Forexample,tohavethedialogdisplaythequestionmarkicon,specifytheMessageBoxIcon.Questionconstant.
WhentheuserpressesaMessageBoxdialogbuttonitreturnsanappropriateDialogResultconstantvaluetotheprogram.Thesearenamedexactlyastheindividualbuttonlabeltheyrepresent.Forexample,anyMessageBoxdialogOKbuttonreturnstheDialogResult.OKconstant.Theprogramcanthereforeexaminethereturnedvaluetodeterminehowtoproceed.
AlwaysspecifyagraphiciconwhencallingaMessageBoxdialogtohelptheusereasilyunderstandthenatureofthemessage.
Message
StartanewWindowsFormsApplication,thenaddaButton,aTextBox,andaLabelcontroltotheForm
Double-clickthe“ShowMessage”ButtoncontroltoopentheCodeEditoratitsgeneratedClickevent-handler
Insertablockwithinthe“ShowMessage”ButtonClickevent-handlertodeliberatelythrowanexceptiontry{thrownewNotImplementedException();
}catch(NotImplementedExceptionnotImp){//Statementstobeinsertedhere(Steps4-5).
}
Addastatementtoassigntheuser’sdecisiontoavariableDialogResultresult=MessageBox.Show(“Proceed?”,notImp.Message,MessageBoxButtons.YesNo,MessageBoxIcon.Error);
Now,addstatementstorespondtotheuser’sdecisiontextBox1.Text=result.ToString();if(result==DialogResult.Yes)label1.Text=“Proceeding...”;if(result==DialogResult.No)label1.Text=“Stopping...”;
PressStartorF5toruntheapplicationandusetheMessageBoxbuttonstodeterminehowtoproceed
ThistechniqueofthrowingaNotImplementedExceptionisfavoredbysomeprogrammersasaremindertocompleteanunfinishedpartoftheprogramcode.
Alternatively,thisprogramcouldstopbycallingtheform’sClose()methodinresponsetoDialogResult.No.
CallingsystemdialogsVisualStudiomakesitsimpletoaddtheabilitytocalluponthestandardWindowsselectiondialogssotheusercanchooseoptionswithinyourapplications.Forexample,selectionofcolors,fonts,andimages:
Dialog
StartanewWindowsFormsApplicationprojectandaddaPictureBox,TextBox,andthreeButtoncontrolstotheForm
FromtheDialogssectionoftheToolbox,addaColorDialog,FontDialog,andOpenFileDialogcomponenttotheForm–seethemappearintheComponentTrayatthebottomoftheFormDesigner
Double-clickthefirstButtontoopentheCodeEditoratitsgeneratedClickevent-handler,theninsertthiscodetochangethebackgroundcoloroftheFormif(colorDialog1.ShowDialog()==DialogResult.OK)this.BackColor=colorDialog1.Color;
Double-clickthesecondButtontoopentheCodeEditoratitsgeneratedClickevent-handler,theninsertthiscodetochangethefontoftheTextBoxcontrolif(fontDialog1.ShowDialog()==DialogResult.OK)textBox1.Font=fontDialog1.Font;
Double-clickthethirdButtontoopentheCodeEditoratitsgeneratedClickevent-handler,theninsertthiscodetochooseanimageforthePictureBoxcontrolif(openFileDialog1.ShowDialog()==DialogResult.OK){//Statementstobeinsertedhere(Step6).
}
TheDialogResult.OKvalueindicatestheuserpressedtheOKbutton–justasitdoesintheMessageBoxexamplehere.
TheSaveFileDialogisdemonstratedintheexamplehere.
Insertablocktoassignaselectedimageordisplayanerrormessagetry{pictureBox1.SizeMode=
PictureBoxSizeMode.StretchImage;pictureBox1.Image=
newBitmap(openFileDialog1.FileName);}catch(Exceptionerror){MessageBox.Show(“Error:SelectAnImageFile!”);
}
PressStartorF5toruntheapplicationandcallthesystemdialogstochooseprogramoptions
ThePictureBoxSizeMode.StretchImagepropertywillstretch,orshrink,aselectedimagetofitthePictureBoxdimensionsasanewBitmapimage.
CreatingapplicationmenusDropdownmenus,toolbars,andstatusbars,likethosefoundinmostWindowsapplications,caneasilybeaddedtoyourownC#GUIapplicationsfromtheToolbox:
Jotter
StartanewWindowsFormsApplicationprojectandfindtheMenus&ToolbarssectionoftheToolbox,thendouble-clicktheMenuStripitemtoaddittotheForm
ClicktheMenuStripcontrol’sarrowbuttontoopenitsSmartTag,thenselectInsertStandardItems
WhenthefamiliarheadingsanditemshavebeenaddedtotheMenuStrip,right-clickonanyitemandusethecontextmenutoeditthatitem.Also,typenewcustomitemsintotheTypeHereboxasrequired
IntheToolbox,double-clickontheToolStripitemtoaddittotheForm,thenopenitsSmartTagandoncemoreselectInsertStandardItems
Alternatively,youcancreateyourowncustommenususingtheTypeHereboxinsteadofInsertStandardItems.
WhenthefamiliariconbuttonshavebeenaddedtotheToolStrip,right-clickonanyitemandusethecontextmenutoeditthatitem.Alsoaddfurthercustomitemsfromthedrop-downlistasrequired
IntheToolbox,double-clickontheStatusStripitemtoaddittotheForm
SelecttheStatusLabelitemontheStatusStripdrop-downlist,andsetitstextpropertyto“Ready”
AddaRichTextBoxcontroltothecenteroftheForm,openitsSmartTagandselecttheoptiontoDockinparentcontainer,thenensurethatitsScrollBarspropertyissettoBoth
UseStatusBarmessagestoprovidefeedbacktotheuser.
Themenusarenottrulyfunctionaluntilyouaddsomeprogramcode–asdescribedhere.
MakingmenusworkThemenuitemsandtoolbarbuttonscreatedherewillnottrulyfunctionuntilyouaddcodetomakethemwork.Foractionsthatappearbothinamenuandonabutton,youcancreateamethodthatcanbecalledfromtheClickevent-handlerofthemenuitemandthatofthebutton–toavoidduplication:
Jotter
InFormDesigner,clickFile,NewtoselecttheNewmenuitem
Double-clickontheNewmenuitemtoopentheCodeEditorinitsClickevent-handler,andaddthismethodcallnewFile();
AftertheClickevent-handlerblock,addthismethodtoclearanyexistingtextanddisplayastatusmessageprivatevoidnewFile(){richTextBox1.Text=null;toolStripStatusLabel1.Text=“Ready”;
}
ReturntotheFormDesigner,thendouble-clickontheNewtoolbarbuttontoopentheCodeEditorinthatevent-handler,andaddacalltothemethodabovenewFile();
AddanOpenFileDialogandSaveFileDialogcomponentfromtheDialogssectionoftheToolbox
IntheClickevent-handlersofboththeOpenmenuitemandtheOpentoolbarbutton,addthismethodcallopenFile();
WhenyouenableNew,Open,andSavedialogs,keyboardshortcutsarealreadyconfigured–tryCtrl+N,Ctrl+S,andCtrl+Ototestthem.
AftertheClickevent-handlerblocks,addthismethodtoloadaplaintextfileprivatevoidopenFile(){openFileDialog1.Filter=“TextFiles|*.txt”;if(openFileDialog1.ShowDialog()==DialogResult.OK){richTextBox1.LoadFile(openFileDialog1.FileName,
RichTextBoxStreamType.PlainText);}
}
IntheClickevent-handlersofboththeSavemenuitemandtheSavetoolbarbutton,addthismethodcallsaveFile();
AftertheClickevent-handlerblocks,addthismethodtosaveaplaintextfileprivatevoidsaveFile(){saveFileDialog1.Filter=“TextFiles|*.txt”;if(saveFileDialog1.ShowDialog()==DialogResult.OK){richTextBox1.SaveFile(saveFileDialog1.FileName,
RichTextBoxStreamType.PlainText);}
}
PressStartorF5toruntheapplicationandtestthefunctionalityoftheNew,Open,andSavefilemenuitemsandtoolbarbuttons
YoucanchangetheFilterto“RichText|*.rtf”andRichTextBoxStreamTypepropertyto.RichTextforfileswithembeddedobjects,suchasimages.
TomaketheFile,Exitmenuitemfunctional,simplyaddthecallApplication.Exit();toitsClickevent-handler.
ImportingaudioresourcesSoundfilescanbeincludedwithinanapplicationasaresource,inmuchthesamewaythatimagefilescanbeimportedasaresource,toenhancetheapplication.Thesecanthenbeplayed,asrequired:
Sound
StartanewWindowsFormsApplicationprojectandaddasingleButtoncontroltotheForm
SelectProject,ProjectNamePropertiesontheMenuBar,toopentheProjectDesignerwindow
InProjectDesigner,selecttheResourcesitemintheleftpane,thenchooseAudioitemfromthedrop-downlist
SelecttheAddExistingFile...itemfromtheAddResourcedrop-downlisttolaunchtheAddexistingfiletoresourcesdialog
ItisadvisabletousetheProjectDesignertoremovearesource,ratherthandeletingitfromSolutionExplorer.
YoucantypicallyfindtheWindowssoundfilesinthefolderonyourcomputeratC:\Windows\Media.
Browsetothelocationofthesoundfileyouwishtoadd,thenselectthefileandclicktheOpenbutton
ThesoundfilenowgetsaddedtotheResourcesfolderinSolutionExplorerandappearsintheResourceswindowofProjectDesigner–hereit’safilenamednotify.wav
Now,opentheCodeEditorandaddadirectiveatthebeginningofthepagetomakeanotherC#classavailableusingSystem.Media;
Double-clicktheButtoncontrol,thenaddthisstatementaboveitsClickevent-handlerblocktocreateanobjectSoundPlayernotifier=newSoundPlayer(Properties.Resources.notify);
Now,addthesestatementsinsidetheButtoncontrol’sClickevent-handlertoshowa
messageandplaythesoundlabel1.Text=“Notifying...”;notifier.Play();
PressStartorF5toruntheapplicationandpushtheButtontohearthesoundplay
AsoundcanbeplayedrepeatedlyusingthePlayLooping()method–andtheloopcanbeendedwiththeStop()method.
Thesoundfilenameonlyisdot-suffixedtoProperties.Resources–withoutitsfileextension.
Summary• TheWindowsFormsApplicationtemplateintheNewProjectdialogisusedtobegina
WindowsGUIproject.
• TheFormDesignerwindowoftheVisualStudioIDEiswhereyoucreatetheapplication’svisualinterface.
• ThePropertieswindowcontainsdetailsoftheitemthatiscurrentlyselectedintheFormDesignerwindow.
• TheCommonControlssectionoftheToolboxcontainsawiderangeofvisualcontrolstobuildGUIapplications.
• TheCodeEditorisusedtocreatethecode-behindpagethatdetermineshowtheapplicationrespondstointerfaceevents.
• WhentheuserpushesaButtoncontrol,itcreatesaClickeventtowhichitsevent-handlercanrespond.
• UserinputintoaTextBoxcontrolcanbeassignedtoavariableforusewithintheapplication.
• TheusercannotmodifytextthatappearsonaLabelcontrol.
• OnlyoneoptioncanbecheckedinaRadioButtongroup,butanynumberofoptionscanbecheckedinaCheckBoxgroup.
• AListBoxcontrolhasanItemspropertythatprovidesmethodstoaddorremoveitemsfromthelistitcontains.
• TheShow()methodoftheMessageBoxclassacceptsargumentstospecifyamessage,caption,buttons,andicon.
• TheDialogssectionoftheToolboxcontainscomponentsthatallowanapplicationtousetheWindowssystemdialogs.
• TheMenus&ToolbarssectionoftheToolboxcontainscomponentsthatallowanapplicationtoincludethefamiliarWindowssystemmenuitems.
• TheMenus&ToolbarscomponentswillnottrulyfunctionuntilcodeisaddedtotheirClickevent-handlers.
• TheProjectDesignerwindowcanbeusedtoimportresourcesintoanapplicationproject.
• ASoundPlayerobjectcanbecreatedusingtheSystem.Mediaclass,andprovidesmethodstohandleaudioresources.
11
Buildinganapplication
Thischapterdemonstrateshowtocreate,test,andpublishasimpleC#programapplication.
PlanningtheprogramAssigningfixedpropertiesDesigningthelayoutSettingdynamicpropertiesAddingruntimefunctionTestingtheprogramPublishingtheapplicationSummary
PlanningtheprogramWhencreatinganewapplicationitisusefultospendsometimeplanningitsdesign.Clearlydefinetheprogram’sprecisepurpose,decidewhatapplicationfunctionalitywillberequired,thendecidewhatinterfacecomponentswillbeneeded.
Aplanforasimpleapplicationtopicknumbersforalotterygameentrymightlooklikethis:
Programpurpose
• Theprogramwillgenerateaseriesofsixdifferentrandomnumbersintherange1–59,andhavetheabilitytobereset.
Omissionoftheplanningstagecanrequiretime-consumingchangestobemadelater.It’sbetterto“planyourwork,thenworkyourplan”.
Functionalityrequired
• Arandomnumbergenerator.
• Amethodtodisplaysixdifferentrandomnumbers.
• Amethodtoclearthelastseriesfromdisplay.
Componentsneeded
• SixLabelcontrolstodisplaytheseriesofnumbers–onenumberperLabel.
• OneButtoncontroltogenerateanddisplaythenumbersintheLabelcontrolswhenthisButtonisclicked.ThisButtonwillnotbeenabledwhennumbersareondisplay.
• OneButtoncontroltoclearthenumbersondisplayintheLabelcontrolswhenthisButtonisclicked.ThisButtonwillnotbeenabledwhennonumbersareondisplay.
• OnePictureBoxcontroltodisplayastaticimage–justtoenhancetheappearanceoftheinterface.
TogglethevalueofaButton’sEnabledpropertytosteertheuser.Inthiscase,theapplicationmustberesetbeforeafurtherseriesofnumberscanbegenerated.
HavingestablishedaprogramplanmeansyoucannowcreatetheapplicationbasicsbyaddingthecomponentsneededtoaForm:
Lotto
OpentheVisualStudioIDEandcreateanewWindowsFormsApplicationprojectcalled“Lotto”
IntheFormDesigner,addsixLabelcontrolstotheFormfromtheToolbox
Now,addtwoButtoncontrolsandaPictureBoxcontroltotheForm
VisualStudio2015supportsclassicdesktopappdevelopmentfortheWindowsStore.
YoucandraganddropitemsfromtheToolbox,ordouble-clickthemtoaddthemtotheForm.
AssigningfixedpropertiesHavingcreatedtheapplicationbasicshere,youcannowassignstaticvaluesusingthePropertieswindow:
Lotto
ClickontheFormtoselectit,theninthePropertieswindow,settheForm’sAppearance,Textpropertyto“LottoNumberPicker”
SelectthefirstButtoncontrol,theninthePropertieswindow,changeitsDesign,(Name)propertytoBtnPick,anditsAppearance,Textto“GetMyLuckyNumbers”
SelectthesecondButtoncontrol,theninthePropertieswindow,changeitsDesign,(Name)propertytoBtnReset,anditsAppearance,Textpropertyto“Reset”
YoucanopenthePropertieswindowusingtheF4key,orbyclickingView,PropertiesWindowontheMenuBar.
TheLabelcontrolsinthisprogramwillhavetheirTextpropertyvaluesassigneddynamicallyatruntime–noinitialpropertiesarerequired.
SelectthePictureBoxcontrol,theninthePropertieswindow,clicktheAppearance,ImagepropertyellipsisbuttontolaunchtheSelectResourcesdialog
ClicktheImportbutton,browsetotheimagelocation,thenclickOKtoimporttheimageresource–thisactionautomaticallyassignsittothePictureBox’sImageproperty
ClickFile,SaveForm1.csorpresstheCtrl+Skeystosavethechangesmadetotheprojectformproperties
Youcanusethedrop-downlistatthetopofthePropertieswindowtoselectanycontrolontheform.
SaveyourprojectperiodicallyasyoubuilditusingFile,SaveAllontheMenuBarorCtrl+Shift+Skeys.
DesigningthelayoutHavingassignedfixedpropertyvalueshere,youcannowdesigntheinterfacelayout.
ThesizeofboththePictureBoxcontrolandtheBtnPickcontrolfirstneedstobeadjustedtoaccommodatetheircontent.ThiscaneasilybeachievedbyspecifyinganAutoSizevaluesothatVisualStudiowillautomaticallyfitthecontrolneatlyarounditscontent:
Lotto
SelectthePictureBoxcontrol,theninthePropertieswindow,changeitsBehavior,SizeModetoAutoSize
SelecttheBtnPickcontrol,theninthePropertieswindow,setitsLayout,AutoSizepropertytoTrue
SeethatthePictureBoxcontrolnowsnuglyfitsaroundtheimage,andtheBtnPickcontrolhasexpandedtofititstext
HolddowntheleftmousebuttonanddragaroundtheLabelstoselectallLabelcontrols
Now,clickView,Toolbars,LayouttoaddtheLayouttoolbartotheVisualStudiomenus
ClicktheAlignTopsbuttontostacktheLabelsinapile
Alternatively,youcanusetheSmartTagarrowbuttononaPictureBoxcontroltosetitsSizeModeproperty.
EnsurethatallPictureBoxMarginpropertiesaresettozeroifyoudonotrequiremarginsaroundtheimage.
ClicktheMakeHorizontalSpacingEqualtoolbarbuttontoarrangethepileofLabelsintoarow
UsetheForm’srightgrabhandletoextenditswidthtoaccommodatetherowofLabelsandPictureBox,thendragtherowandbothButtonstotoprightoftheForm
DragthePictureBoxcontroltotopleftoftheForm,thenusetheForm’sbottomgrabhandletoadjustitsheighttomatchthatoftheimage
UsetheSnapLinesthatappearwhenyoudragcontrolsaroundtheFormtopositiontherowofLabelsandtheButtonstomaketheinterfacelooklikethelayoutbelow
SettheForm’sWindowStyle,MaximizeBoxandMinimizeBoxpropertiestoFalse,asmaximizeandminimizebuttonsarenotrequiredonthisinterface
Inthiscase,itdoesnotmatterinwhatordertheLabelsappearintherow.
Avoidthetemptationtochangethedefaultstylesofformcontrolssotheyremainfamiliartousers.
SettingdynamicpropertiesHavingdesignedtheinterfacehere,youcannowaddsomefunctionalitytodynamicallysettheinitialTextpropertiesoftheLabelcontrolsandtheinitialButtonstates:
Lotto
ClickView,CodeontheMenuBar,orpressF7,toopentheCodeEditorwindow
AftertheForm1()constructormethodblock,addanewmethodblockprivatevoidClear(){//Statementstobeinsertedhere(Steps4-8).
}
Withthecursorinsidethenewmethodblock,pressCtrl+J,toopentheIntelliSensepop-upwindow
ScrolldownthelistofitemsintheIntelliSensewindowanddouble-clickonthelabel1itemtoadditintotheClear()methodblock
Typeaperiod,thendouble-clicktheTextitemwhentheIntelliSensewindowreappears,toaddthatcode
ThetechniquedescribedheredemonstrateshowtouseIntelliSense–butyoucan,ofcourse,justtypethecodedirectly.
Now,type=“...”;tocompletethelinesoitreadslikethis:label1.Text=“...”;
RepeatthisprocedurefortheotherLabelcontrols–sothattheClear()methodassignseachanellipsisstring
WiththecursorinsidetheClear()methodblock,useIntelliSenseinthesameway,toaddthesetwolines:BtnPick.Enabled=true;BtnReset.Enabled=false;
Type“Intellisense”intotheQuickLaunchboxatthetopoftheVisualStudiowindowtodiscovertheIntelliSenseMenusandOptions.
ThiscompletestheClear()methodfunctionalitybysettingtheButtonstates.AllthatremainsistoaddacalltotheClear()methodtoexecuteallofitsinstructionswhentheprogramstarts.
IntheFormDesignerdouble-clickontheFormtoopentheCodeEditorinitsLoadevent-handler,thenpressCtrl+JtoopentheIntelliSensewindow
ScrolldownthelistintheIntelliSensewindowanddouble-clickontheClearitemyouhavejustcreated,toaddacallstatementintheLoadevent-handler
Youcouldaddsomecommentstomakethecodemorefriendly.
AddingruntimefunctionHavingcreatedcodetoinitializedynamicpropertieshere,youcannowaddruntimefunctionalitytorespondtoclicksontheButtoncontrols:
Lotto
IntheFormDesigner,double-clickontheBtnResetButtoncontroltoopentheCodeEditorinitsClickevent-handler,thenaddthismethodcallClear();
ThisisallthatisneededtoprovidedynamicfunctionalityfortheBtnResetcontrol.ThemaindynamicfunctionalityofthisapplicationisprovidedbytheBtnPickcontrol,whichrequiresaninstanceofaRandomclass,randomnumbergeneratorobject:
IntheFormDesigner,double-clickontheBtnPickButtoncontroltoopentheCodeEditorinitsClickevent-handler
IntheClickevent-handlerblock,addthisstatementtocreatearandomnumbergeneratorobjectRandomrnd=newRandom();
Next,addastatementtocreateanarrayof59elementstostoreasequenceofnumbersint[]seq=newint[59];
Now,addalooptofillthearrayelements(index0to58)withintegervalues1to59for(inti=1;i<60;i++){seq[i-1]=i;
}
Addasecondlooptoshufflethevalueswithinallthearrayelements–analgorithmtorandomizetheirorderfor(inti=0;i<59;i++){intj=(rnd.Next()%59);intk=seq[i];seq[i]=seq[j];seq[j]=k;
}
Therandomnumbergeneratorisusedheretogeneraterandomvaluesbetweenzeroand58toshufflearrayelements.
Youdon’tneedtounderstandindetailthealgorithmthatisusedtoshufflethevalues.
Next,addthefollowinglinestodisplaythenumberscontainedinarrayelements1-6intheLabelcontrolslabel1.Text=seq[1].ToString();label2.Text=seq[2].ToString();label3.Text=seq[3].ToString();label4.Text=seq[4].ToString();label5.Text=seq[5].ToString();label6.Text=seq[6].ToString();
Now,addthesetwolinestosettheButtonstatesreadytoresettheapplicationBtnPick.Enabled=false;BtnReset.Enabled=true;
Addcommentsforothersexaminingthecode,andforyourselfwhenrevisitingthecodelater
ClickFile,SaveAllorpresstheCtrl+Shift+Skeystosavethechangesmadetotheprojectcode-behindpage
TheLabelcontrolscanonlycontainstringvalues,sotheintnumericvaluesmustbeconverted.
YoucanhaveVisualStudionicelyformatyourcodebyselectingEdit,Advanced,FormatDocument,orusingthekeyboardshortcutshownthere–typically,thisisCtrl+K,Ctrl+D.
TestingtheprogramHavingworkedthroughtheprogramplanonthepreviouspages,thecomponentsneededandfunctionalityrequiredhavenowbeenaddedtotheapplication–soit’sreadytobetested:
Lotto
ClicktheStartbutton,orpressF5,toruntheapplicationthenexamineitsinitialstart-upappearance
TheForm’sLoadevent-handlerhassettheinitialdynamicvaluesofeachLabelcontrolanddisabledtheresetbuttonasrequired.
ClicktheBtnPickButtoncontroltoexecutetheinstructionswithinitsClickevent-handler
Noticethatnonumberisrepeatedinanyseries.
Aseriesofnumberswithinthedesiredrangeisdisplayed,andtheButtonstateshavechangedasrequired–afurtherseriesofnumberscannotbegenerateduntiltheapplicationhasbeenreset.
Makeanoteofthenumbersgeneratedinthisfirstseriesforcomparisonlater
ClicktheBtnResetcontroltoexecutetheinstructionswithinthatClickevent-handlerandseetheapplicationreturntoitsinitialstart-upappearanceasrequired
ClicktheBtnPickButtoncontrolagaintoexecuteitsClickevent-handlercodeasecondtime
Rememberthatthisapplicationinterfacehasnominimizeormaximizebuttonsbecausetheirpropertiesweresettofalse–here,Step11.
Anotherseriesofnumberswithinthedesiredrangeisdisplayedandaredifferenttothoseinthefirstserieswhencompared–good,thenumbersarebeingrandomizedasrequired.
ClicktheStopDebuggingbutton,thenclicktheStartbuttontorestarttheapplicationandclicktheBtnPickButtoncontroloncemore
Thegeneratednumbersinthisfirstseriesofnumbersaredifferenttothosenotedinthefirstseriesthelasttimetheapplicationran–great,therandomnumbergeneratorisnotrepeatingthesamesequenceofnumberserieseachtimetheapplicationruns.
Alternatively,youcanclicktheapp’sXbuttontoclosetheapplicationandstopdebugging.
PublishingtheapplicationHavingsatisfactorilytestedtheapplicationhere,youcannowcreateastand-aloneversionthatcanbeexecutedoutsidetheVisualStudioIDE,andthatcanbedistributedtoothersfordeploymentelsewhere.
Lotto
ClickProjectontheMenuBar,chooseLottoProperties,SigningthenselectasignaturecertificateorensuretheSigntheClickOncemanifestsboxisunchecked
ClickBuild,BuildLotto,thenclickBuild,PublishLottotolaunchthePublishWizarddialog
Usethewizard’sBrowsebuttontoselectalocationwhereyouwishtopublishtheapplication–thechosenlocationshownhereistherootdirectoryofremovabledriveF:
ClicktheNextbutton,thenselectwhethertheuserwillinstalltheapplicationfromawebsite,network,orportablemediasuchasCD,DVD,orremovabledrive–inthiscaseacceptthedefaultportablemediaoption
Applicationssigningisoptional,butdoesverifyauthentication.FindmoredetailsonClickOnceatmsdn.microsoft.com/en-us/library/t71a733d.aspx
Whenchoosingapublishlocation,usetheCreateNewFolderbuttonintheFileSystemdialogtomakeafoldertocontainalltheapplicationfiles.
ClicktheNextbutton,thenselectwhethertheinstallershouldcheckforapplicationupdates–acceptthedefaultoptionnottocheckforupdatesinthiscase
ClicktheNextbuttontomovetothefinaldialogpage,confirmthelistedchoices,thenclicktheFinishbuttontopublishtheapplicationatthespecifiedlocation
Eachtimeyoupublishanapplication,itsversionnumberisautomaticallyincremented–1.0.0.0,1.0.0.1,1.0.0.2,etc.
ThePublishWizardgeneratesanumberoffiles,includingafamiliar“setup.exe”executableinstaller.
Movetheportablemediatothesystemwhereitistobedeployed,thenrunsetup.exetoinstalltheapplication
Whentheapplicationisinstalledontheclientsystem,ashortcutisautomaticallyaddedtotheStartmenu,whichcanbeusedtolaunchtheapplication.Theusercanthenruntherelease
versionoftheapplicationjustasitperformedduringtestingofitsdebugversionintheVisualStudioIDE.
Theinstalleralsoaddsanitemtotheclientsystem’sAdd/RemoveProgramslist,whichcanbeusedtouninstalltheapplication–justlikeanyotherWindowsprogram.
Anapplicationcannotbepublishedunlessithasbeenbuiltfirst.
Summary• Alwaysmakeaninitialprogramplan,toavoidtheneedfortime-consumingchangeslater.
• Aprogramplanshouldclearlydefinetheprogrampurpose,functionalityrequired,andcomponentsneeded.
• FixedpropertiesthatwillnotchangewhentheapplicationisrunningcanbesetatDesigntimeinthePropertiesWindow.
• TheImportbuttonintheSelectResourcesdialogcanautomaticallyassignanimagetoaPictureBoxcontrol.
• AnAutoSizepropertyvaluemakesVisualStudioautomaticallyfitacontrolneatlyarounditscontent.
• TheFormDesigner’sLayouttoolbarcontainsusefulfeaturestoquicklyalignandspacemultipleinterfacecontrols.
• SnapLineshelpyoutoeasilyalignaselectedcontroltoothersintheinterfaceatDesigntime.
• SettingaForm’sWindowStyle,MaximizeBoxandMinimizeBoxpropertiestoFalseremovesthosebuttons.
• DynamicpropertiesthatwillchangewhentheapplicationisrunningcanbeinitializedwiththeForm’sLoadevent-handler.
• Thepop-upIntelliSensewindowletsyoueasilyaddprogramcodewhenusingtheCodeEditor.
• Runtimefunctionalityrespondstouseractionsbychangingdynamicproperties.
• ADebugversionofanapplicationallowsitsfunctionalitytobetestedastheapplicationisbeingcreatedintextformat.
• TheBuildprocesscompilesaReleaseversionofanapplicationinbinaryformat.
• ThePublishprocesscreatesafinalReleaseversionwithaninstallersotheapplicationcanbedeployedelsewhere.
• ApplicationscreatedwiththeVisualStudioIDEcanbeinstalledanduninstalledjustlikeotherWindowsapplications.
12
Targetingdevices
ThischapterdemonstrateshowtocreateaUniversalWindowsPlatformapplicationusingC#programming.
StartingaUniversalprojectInsertingpagecomponentsImportingprogramassetsDesigningthelayoutAddingruntimefunctionTestingtheprogramAdjustingtheinterfaceDeployingtheapplicationSummary
StartingaUniversalprojectWindows10introducedtheUniversalWindowsPlatform(UWP)whichenablesyoutocreateasingleapplicationthatwillrunonanymodernWindows-baseddevice–phone,tablet,orPC.
TheinterfacelayoutofaUWPapplicationusestheeXtensibleApplicationMarkupLanguage(XAML)tospecifycomponents.
TheexampleinthischapterisforVisualStudio2015onWindows10–itwon’tworkwithearlierversions.
InordertodevelopappsfortheUWP,youshouldberunningthelatestversionofWindows10,andyourVisualStudioIDEmustincludetheUniversalWindowsAppDevelopmentTools:
Universal
OpenControlPanel,ProgramsandFeatures,thenright-clickontheVisualStudioitemandselectChange–tolaunchtheVisualStudioinstaller
SelectalloptionsintheUniversalWindowsAppDevelopmentToolscategory,thenclicktheNextbutton–todownloadandinstallthetools
Afterinstallationofthetools,opentheVisualStudioIDE
AUWPapplicationisalsoknownasa“UWA”–UniversalWindowsApplication.
DependinguponyourchoiceswhenyouinstalledVisualStudio,youmayseetheoptionscheckedwhentheinstallerlaunches,toindicateyoualreadyhavetheUniversalWindowsAppDevelopmentTools.
Next,selectFile,New,ProjectandcreateanewBlankApp(UniversalWindows)projectcalled“Universal”
Whenaskedtoselectthetargetandminimalplatformversions,simplyclickOKtoaccept
thedefaultoptions
AfterVisualStudiocreatesthenewproject,selectView,SolutionExplorertoexaminethegeneratedfiles:
• AsetoflogoimagesinanAssetsfolder
• InternalXAMLandC#filesfortheApp
• XAMLandC#filesfortheMainPage–hereiswhereyouwillcreateinterfacecomponentsandfunctionalcode
• OthermiscellaneousPackagefiles
OnWindows10youshouldensurethattheDeveloperModeoptionisenabledinSettings,Update&Security,Fordevelopers.
VisualStudio2015supportscross-platformmobiledevicedevelopment.
ThesefilesareessentialtoallUWPappsusingC#,andexistineveryprojectVisualStudiocreatestotargettheUniversalWindowsPlatformwithC#.
InsertingpagecomponentsVisualStudioprovidesatwo-partwindowtoinsertinterfacecomponentsintoaUWPapp.ThiscomprisesaDesignviewofthecomponentsandaXAMLviewfortheXAMLcode:
Universal
OpenSolutionExplorerthendouble-clickonMainPage.xaml–tolaunchthetwo-partwindow
Seethat,bydefault,theDesignviewdisplaysablankcanvasinPortraitmode
Explorethesebuttonstochangethemagnificationandgridcharacteristics.
ClicktheadjacentbuttoninDesignviewtochangetheblankcanvastoLandscapemode
XAMLispronounced“zammel”.
ThereisaToolboxthatletsyouaddcomponentsontothecanvas,butyouwillneedtoeditthemintheXAMLcodelater.Inthisexample,thecomponentsarecreatedinXAMLcodefromtheverystart.
Now,seethatbydefault,theXAMLviewrevealsthereare<Grid></Grid>tags–thisistherootelementofthecanvasinwhichyoucanaddcomponentelements
Componentelementsarebestnestedwithina<StackPanel>element,asthiscanbegivenanx:Nameforreferenceinfunctionalcode,andanOrientationattributetospecifythedirectioninwhichthenestedelementsshouldappear.Commoncomponentelementsinclude<Image>,<TextBox>,<TextBlock>(label),and<Button>.Several<StackPanel>elementscanbenestedwithineachothertodeterminetheHorizontalandVerticallayoutofcomponents:
Insertelementsbetweentheroot<Grid></Grid>tags,sotheXAMLviewcodelookspreciselylikethis:
AsyouaddthecomponentelementsinXAMLview,theyappearintheDesignviewuntilitlookslikethis:
Thex:prefixbeforetheNameattributereferstotheXAMLschemausedbyUWPapps.
Theouter<StackPanel>isahorizontallayoutcontainingan<Image>andanested<StackPanel>.Thenested<StackPanel>isaverticallayoutcontainingtwofurther<StackPanel>elementsthateachdisplaytheircomponentshorizontally.
Noticethateach<TextBlock>elementhasaTextattributethatcanbereferencedinfunctionalcode.Forexample,textBlock1.Text.
ImportingprogramassetsInordertohaveaXAML<Image>componentdisplayagraphic,animagefilefirstneedstobeaddedtotheprojectsAssetsfolder.ItcanthenbeassignedtoaSourceattributeofthe<Image>tag:
Universal
OpenSolutionExplorer,thenright-clickontheAssetsfolderandchooseAddfromthecontextmenu
Now,chooseExistingItemfromthenextcontextmenu–toopenanAddExistingItemdialogbox
IntheAddExistingItemdialog,browsetothelocationofanimage,thenselectthefileandclicktheAddbutton
Animagefordisplaymaybeinanypopularfileformat–suchas.bmp,.gif,.jpg,.png,or.tif.
InSolutionExplorer,theselectedimagefilenowappearsintheproject’sAssetfolder
SelecttheImagecomponentinDesignerview,thenclickView,Propertiestorevealitsproperties
InthePropertieswindow,expandtheCommoncategory,thenclicktheSourceitem’sarrowbuttonandselecttheaddedimagefromthedrop-downlist
TheimagenowappearsintheDesignview,anditspathgetsaddedtotheXAMLviewcodeandSourceproperty
ExploretheAppearanceandTransformoptionsinanimage’sPropertieswindow,todiscoverhowyoucanmodifyhowitwillbedisplayed.
DesigningthelayoutTocompletetheapp’slayout,designattributescanbeaddedtotheXAMLelementtagstospecifywhattheywilldisplayandpreciselywhereintheinterfacetheywillappear:
Universal
OpenMainPage.xaml,thenaddtwoattributestotheouter<StackPanel>elementtofixitspositionHorizontalAlignment=”Left”VerticalAlignment=”Top”
Next,editthe<Image>elementbymodifyingtheinitialassignedvalueof200–toincreaseitswidthWidth=”300”
Now,addanattributetothenested<StackPanel>elementtofixitspositionVerticalAlignment=”Center”
Then,editallsix<TextBlock>elementsalike,tospecifytheirinitialcontent,width,andmarginonallfoursidesText=”...”Width=”20”Margin=”15”Text=”...”Width=”20”Margin=”15”Text=”...”Width=”20”Margin=”15”Text=”...”Width=”20”Margin=”15”Text=”...”Width=”20”Margin=”15”Text=”...”Width=”20”Margin=”15”
Editthefirst<Button>elementtorenameit,specifyitsbuttonlabelcontent,andmarginonallfoursidesx:Name=“BtnPick”Content=“GetMyLuckyNumbers”Margin=“15”
Editthesecond<Button>elementtorenameitandspecifyitsbuttonlabelcontentx:Name=“BtnReset”Content=“Reset”
Finally,addanattributetoeachrespective<Button>elementtospecifytheirinitialstateIsEnabled=“True”IsEnabled=“False”
AsingleMarginvaluesetsallfourmarginsaroundthatcomponent.Youcanspecifytwo
valuestosetleft&right,top&bottommargins,e.g.Margin=“10,30”.Alternatively,youcanspecifyfourvaluestosetleft,top,right,bottommarginsindividually,e.g.Margin=“10,30,10,50”.
Theorderinwhichtheattributesappearineachelementisunimportant,buttheelementswithintheMainPage.xamlfileshouldnowlooksimilartothescreenshotbelow:
YoucanoptionallyaddMargin=“0”attributestoexplicitlyrequireelementstohavenomarginwidth.
AsyoumakechangestotheXAMLviewcode,thecomponentlayoutgetschangedaccordinglyintheDesignviewandshouldnowlooklikethis:
TheDesignviewshowsthecomponents’initialstate–theResetbuttonappearsgrayedout,asitisnotenabled.
AddingruntimefunctionHavingcompletedtheapplicationcomponentlayoutwithXAMLelementshere,youarenowreadytoaddfunctionalitywithC#programmingcode:
Universal
InDesignview,double-clickontheBtnPickbutton
TheMainPage.xaml.cscode-behindpageopensintheCodeEditoratageneratedBtnPick_Clickevent-handler
IntheBtnPick_Clickevent-handlerblock,insertthesestatementstocreatearandomizedarrayofintegersbetween1and59Randomrnd=newRandom();int[]seq=newint[59];for(inti=1;i<60;i++)seq[i-1]=i;for(inti=0;i<59;i++){intj=(rnd.Next()%59);intk=seq[i];seq[i]=seq[j];seq[j]=k;
}//Statementstobeinsertedhere(Steps4-5).
Next,insertstatementstoassignsixarrayelementvaluestothe<TextBlock>componentstextBlock1.Text=seq[1].ToString();textBlock2.Text=seq[2].ToString();textBlock3.Text=seq[3].ToString();textBlock4.Text=seq[4].ToString();textBlock5.Text=seq[5].ToString();textBlock6.Text=seq[6].ToString();
Next,insertstatementstosetthe<Button>statesBtnPick.IsEnabled=false;BtnReset.IsEnabled=true;
ReturntoMainPage.xaml,theninDesignview,double-clickontheBtnResetbutton
TheMainPage.xaml.cscode-behindpageopensintheCodeEditoratageneratedBtnReset_Clickevent-handler
TherandomizerroutineusesexactlythesamelogicasthatoftheWindowsFormsApplicationexample–seehere.
ThereisnoLabelcomponentinUWPapps;itiscalledaTextBlockinstead.
ThereisnoEnabledpropertyinUWPapps;itiscalledIsEnabledinstead.
IntheBtnReset_Clickevent-handlerblock,insertstatementstoassignstringstothe<TextBlock>componentstextBlock1.Text=“...”;textBlock2.Text=“...”;textBlock3.Text=“...”;textBlock4.Text=“...”;textBlock5.Text=“...”;textBlock6.Text=“...”;//Statementstobeinsertedhere(Step9).
Finally,insertstatementstosetthe<Button>statesBtnPick.IsEnabled=true;BtnReset.IsEnabled=false;
TheBtnResetbuttonsimplyreturnsthe<TextBox>and<Button>componentstotheiroriginalstates.
TheMainPage.xaml.cscode-behindpageshouldnowlooklikethescreenshotbelow:
ReturntotheMainPage.xamlfile,theninXAMLview,seethatattributeshavebeenautomaticallyaddedtothe<Button>elementstocalltheevent-handlercode
Noticethatthefirstforloopcontainsonlyonestatementtobeexecutedoneachiteration,sobracesarenotrequired.
TestingtheprogramHavingaddedfunctionalitywithC#codehere,youarenowreadytotesttheprogramfortwodevices:
Universal
OntheVisualStudiostandardtoolbar,selectDebugforx64architectureandLocalMachineoptions,thenclicktheStartbuttontoruntheappforaPCdevice
Waitwhiletheapplicationgetsbuiltandloaded,thenclickthebuttonstotryouttheirfunctionality
TheapplooksgoodonPCdevices–numbersarebeingrandomizedandthebuttonstatesarechangingasrequired.
Now,ontheVisualStudiostandardtoolbar,selectDebug,StopDebuggingtoexittherunningprogram
YoumusthaveyourPCsettoDeveloperModeinSettings,Update&Security,Fordevelopers.
YoucansafelyignoretheDEBUGnumbersthatappearintheblackboxes,butifyouprefernottoseethem,selectProject,ProjectNameProperties,Build,thenunchecktheDefineDEBUGconstantoption.
OntheVisualStudiostandardtoolbar,selectDebugforx86architectureandsmallMobileEmulatoroptions,thenclicktheStartbuttontoruntheappforamobiledevice
Waitwhiletheemulatorstartsup–thistakesawhile
Whentheapplicationgetsbuiltandloaded,youseethecontrolsarenotvisible–soyoucan’ttryouttheirfunctionality!
What’sgoingonhere?ClickoneoftheemulatorsRotatebuttonstoflipitovertoLandscapeorientationandlookforclues
Ah-ha!Someofthecontrolsarenowvisible,butthisisunsatisfactory–adjustmentswillbeneededtotheinterfacelayoutsotheapplooksgoodonmobiledevices
Again,ontheVisualStudiostandardtoolbar,selectDebug,StopDebuggingtoexittherunningprogram
Testontheemulatorwithlowestmemoryandsmallestscreen,anditshouldbefinerunningonthoseemulatorswithbetterfeatures.
DonotclicktheXbuttonontheemulatorwindowtostoptherunningprogram,asthatwillalsoclosetheemulator.
AdjustingtheinterfaceTheapptestformobiledevicesherefailedtosatisfactorilypresentthecontrols,astheinterfaceistoowideforsmallscreendevices.Happily,theinterfacecanbemadetoadapttodifferentscreensizessoitcanalsolookgoodonmobiledevices.Theadaptationreliesuponrecognizingthescreensizeandchangingtheorientationofa<StackPanel>elementinXAMLfornarrowscreendevices:
Universal
OpenMainPage.xaml,theninXAMLview.addtheseelementsimmediatelybelowtheopening<Grid>elementandbeforethecomponentelements<VisualStateManager.VisualStateGroups><VisualStateGroup>
<!--Elementstobeinsertedhere(Steps2-3)-->
</VisualStateGroup></VisualStateManager.VisualStateGroups>
Next,insertelementstorecognizewidescreens<VisualStatex:Name=“wideState”>
<VisualState.StateTriggers><AdaptiveTriggerMinWindowWidth=“641”/>
</VisualState.StateTriggers>
</VisualState>
Now,insertelementstorecognizenarrowscreens,andtochangetheOrientationoftheouter<StackPanel><VisualStatex:Name=“narrowState”>
<VisualState.StateTriggers><AdaptiveTriggerMinWindowWidth=“0”/>
</VisualState.StateTriggers>
<VisualState.Setters><SetterTarget=“MainStack.Orientation”Value=“Vertical”/>
</VisualState.Setters>
</VisualState>
XAMLcoderecognizesthesame<!---->commenttagsthatareusedinHTMLcode.
Rememberthattheouter<StackPanel>inthisappcontainsan<Image>andanested<StackPanel>displayedhorizontally,sidebyside.Ifdisplayedvertically,theyshouldappearoneabovetheother.
ThebeginningoftheMainPage.xamlfileshouldnowlooksimilartothescreenshotbelow:
Selectx64andLocalMachinetoruntheappforaPCdeviceoncemore–itstilllooksandfunctionswell
Now,selectx86andMobileEmulatortoruntheappforamobiledevice–itnowalsolooksandfunctionswell
YoucanhaveVisualStudionicelyformattheXAMLcodebypressingCtrl+K,Ctrl+D.
Althoughanappmayworkwellonanemulator,itisrecommendedyoualwaystestonactualdevicesbeforedeployment.
DeployingtheapplicationHavingtestedtheappinaMobileEmulatorhere,itcannowbetestedonarealdevicebeforedeployment:
Universal
OnaWindows10device,selectDevelopermodefromtheSettings,Update&Security,Fordevelopersmenu
Next,connectthedevicetoyourPCviaaUSBsocket
OntheVisualStudiotoolbar,selectDebugforARMarchitectureandDeviceoptions,thenclicktheStartbuttontoruntheappontheconnecteddevice
Waitwhiletheapplicationgetsbuiltandloaded,thentapthebuttonstotryouttheirfunctionality
YoucanchoosetheRemoteMachineoptiontotestviaanetworkconnection.
Theapplooksgood,numbersarebeingrandomized,andthebuttonstatesarechangingasrequired–theappcanbedeployed.
RemovetheDebugversionoftheappfromthedevice
InSolutionExplorer,addlogoimagestotheAssetsfolder,thendouble-clickonPackage.appmanifestandaddthemtoVisualAssets
AddthreelogoimagestotheAssetsfolderoftherequiredsizes,thenclickthesebuttonstoselectthemtobetheapptiles.Youcanalsoaddtileimages,aSplashScreenimage,orselecttheApplicationtabandchangetheapp’sDisplayname–to“LuckyNumbers”,forexample.
OntheVisualStudiotoolbar,selectReleaseforARMarchitectureandDeviceoptions,thenclickBuild,DeploySolutiontobuildandinstalltheReleaseversion
YoucanuseyourC#programmingskillstobuildappsforAndroidandiOSwithVisualStudioandXamarin.Discovermoreonlineatxamarin.com
Summary• TheUniversalWindowsPlatform(UWP)enablesasingleapptorunonanymodern
Windows-baseddevice.
• TheeXtensibleApplicationMarkupLanguage(XAML)isusedtospecifycomponentsandlayoutonUWPapps.
• TheUniversalWindowsAppDevelopmentToolsareneededinordertodevelopUWPapps.
• TheBlankApp(UniversalWindows)templatecanbeusedtocreateanewUWPproject.
• VisualStudioprovidesagraphicalDesignviewandatextcodeXAMLviewfortheMainPage.xamlfile.
• ComponentelementscanbeplacedwithinXAML<StackPanel>elementstoarrangetheirorientation.
• ImagefilescanbeaddedtotheAssetsfolderandassignedtoXAML<Image>elementsfordisplayontheinterface.
• SpacecanbeaddedaroundacomponentbyaddingaMarginattributeandassignedvaluewithinitselementtag.
• FunctionalC#programmingcodecanbeaddedtotheMainPage.xaml.cscode-behindpage.
• TheDeveloperModesettingmustbeenabledintheWindows10optionsinordertodevelopandtestUWPapps.
• AUWPappcanbetestedinDebugmodeontheLocalMachine,aMobileEmulator,andaconnectedDevice.
• TheinterfaceofaUWPappcanadapttodifferentscreensizesbychangingtheorientationof<StackPanel>elements.
• ImagefilescanbeaddedtotheAssetsfolderforassignmentaslogosinthePackage.appmanifestwindow.
• TheReleaseversioncanbedeployedbyselectingthetargetconfiguration,thenusingtheBuild,DeploySolutionmenu.