This article explores how a beginner-friendly console application is developed using C# and the .NET Framework 4.8. We delve into the intricacies of creating a menu-driven interface that offers choices such as "Eat Candy," "Go Fishing," and "Play Basketball," culminating in an option to exit the application gracefully. Through a step-by-step walkthrough, we illustrate the process of writing clean, concise code while emphasizing best practices in user interaction.
Figure 1.A screenshot of the console application displaying a menu of choices.
- Introduction
- Prerequisites
- Walkthrough
- Step 1: Creating a New Console Application Project
- Step 2: Adding Enum Definitions
- What is an enum?
- Why are we using an enum?
- Step 3: Writing the Application Logic
- Entire Program.cs File
- Step 4: Running the Application
- Conclusion
This tutorial will create a simple console application using C# and the .NET Framework 4.8. Our application will display a menu of choices to the user, allowing them to perform various actions. We'll implement features such as displaying the menu, handling user input, and confirming actions like exiting the application.
This tip/trick is aimed at beginners and those just beginning to do C# programming language exercises, such as first-year computer science students. Such a problem is frequently given to those learning to program for the first time.
NOTE:I am aware of the existence of C# 12 and .NET Core 8. However, as a personal preference, I believe that using older frameworks has more instructional value. I am specifically choosing to use .NET Framework 4.8 and C# 7 to show students programming concepts such asnamespace
s, etc., that must be more explicitly declared in older versions of C#. Furthermore, as this is not a very advanced tutorial, we can forego using a powerhouse such as .NET Core 8 when .NET Framework on Windows will do just fine, for my purposes.
Prerequisites
- Visual Studio 2022 is installed on your machine.
- Basic understanding of C# programming concepts.
Walkthrough
Step 1: Creating a New Console Application Project
- Open Visual Studio 2022.
- Click theFilemenu, point toNew, and clickProject/Solution.
- In the Create a new projectwindow, search for
Console App (.NET Framework)
". - Choose the
Console App (.NET Framework)
template and clickNext. - Name your project
MenuDemo
and choose a location to save it. - Click Createto create the project.
Step 2: Adding Enum Definitions
Inside the
MenuDemo
project, add a new C# file namedEnums.cs
.Define an enum named
MenuChoices
to represent the menu options. Include options forEatCandy
,GoFishing
,PlayBasketball
, andExit
. Use theDescription
attribute to provide human-readable descriptions for each option.
C#
using System.ComponentModel;namespace MenuDemo{ public enum MenuChoices { [Description("Eat Candy")] EatCandy, [Description("Go Fishing")] GoFishing, [Description("Play Basketball")] PlayBasketball, [Description("Exit")] Exit }}
Listing 1.The definition of the MenuChoices
enumeration.
What is an enum
?
In C#, an enum
(short for "enumeration") is a special data type used to define a set of named integral constants. These constants represent a finite list of possible values that a variable of that enum
type can hold. Each constant in an enum
has an associated integer value, which by default starts from 0 and increments by 1 for each subsequent constant.
Why are we using an enum
?
In our MenuDemo
application, we're using a enum
called MenuChoices
to represent the different options available in our menu. Instead of using raw integer values to represent each choice (e.g., 0 for "Eat Candy", 1 for "Go Fishing", and so on), we use descriptive names like EatCandy
, GoFishing
, etc., making our code more readable and self-explanatory.
Here are some benefits of using an enum
:
Readability: Using descriptive names improves code readability. When someone reads
MenuChoices.EatCandy
, they immediately understand the intended meaning.Type Safety: Enums provide type safety, meaning you can't assign arbitrary values to an enum variable. You're restricted to the predefined set of constants.
Intellisense Support: IDEs like Visual Studio provide IntelliSense support for enums, making selecting the correct value from a list of options easier.
Compile-Time Checks: The compiler performs checks to ensure that enum values are used correctly, reducing the likelihood of errors at runtime.
In summary, enums are a convenient way to define a set of related constants with meaningful names, improving code readability, maintainability, and reliability. They are particularly useful in scenarios where you have a fixed set of options or states, such as menus, application states, days of the week, etc.
Step 3: Writing the Application Logic
Open Solution Explorer.
To do so, click theViewmenu and then clickSolution Explorer.
Expand all the items in Solution Explorer, find the
Program.cs
file, and double-click on it.The
Program.cs
file is now open in the Editor.
Somewhere in the
Program
class, after theMain
method, add code to define theGetUserChoice
method.- This method reads user input from the console.
- It parses the input into a
MenuChoices
enumeration value. - The corresponding value is returned if the input matches any of the enumeration values.
- If the input cannot be parsed into a valid enumeration value, it returns
MenuChoices.Unknown
. - Here's a listing of my
GetUserChoice
method:///<summary>///Readsuserinputfromtheconsoleandparsesitintoa///<seecref="T:MenuDemo.MenuChoices"/>enumerationvalue.///</summary>///<returns>///The<seecref="T:MenuDemo.MenuChoices"/>enumerationvaluecorrespondingto///theuserinput.///Iftheinputcannotbeparsedintoavalidenumerationvalue,returns///<seecref="F:MenuDemo.MenuChoices.Unknown"/>.///</returns>///<remarks>///Thismethodreadsalineoftextfromtheconsoleinputandattemptstoparse///itintoa<seecref="T:MenuDemo.MenuChoices"/>enumerationvalue.///<para/>///Iftheinputmatchesanyoftheenumerationvalues,thecorresponding///enumerationvalueisreturned.///<para/>///Iftheinputcannotbeparsedintoavalidenumerationvalue,themethod///returns<seecref="F:MenuDemo.MenuChoices.Unknown"/>.///</remarks>privatestaticMenuChoicesGetUserChoice(){varinput=Console.ReadLine();returnEnum.TryParse(input,outMenuChoiceschoice)?choice:MenuChoices.Unknown;}
Listing 2.The code of theGetUserChoice
method.
Now, add code for the definition of the GetEnumDescription method:
- If available, this method retrieves the description associated with a given
enum
value. If noDescription
attribute is found, it returns the string representation of theenum
value. - It first gets the field information of the
enum
value using reflection. - It then retrieves the
DescriptionAttribute
associated with the enum value, if any, using theGetCustomAttribute
method. - If a
DescriptionAttribute
is found, it returns the description value associated with it. - If no
DescriptionAttribute
is found, it returns the string representation of the enum value itself. - Here's an example listing of my implementation of GetEnumDescription:
C#
///<summary>///Retrievesthedescriptionattributevalueassociatedwiththespecifiedenum///value.///</summary>///<paramname="value">///The<seelangword="enum"/>valueforwhichtoretrievethe///description.///</param>///<returns>///Thedescriptionassociatedwiththe<seelangword="enum"/>value,if///available;otherwise,the///stringrepresentationofthe<seelangword="enum"/>value.///</returns>///<remarks>///Thismethodretrievesthedescriptionattributevalue,ifpresent,associated///withthespecified<seelangword="enum"/>value.///<para/>///Ifnodescriptionattributeisfound,itreturnsthestringrepresentationof///the<seelangword="enum"/>value.///</remarks>privatestaticstringGetEnumDescription(Enumvalue){varfield=value.GetType().GetField(value.ToString());varattribute=(DescriptionAttribute)Attribute.GetCustomAttribute(field,typeof(DescriptionAttribute));returnattribute==null?value.ToString():attribute.Description;}
Listing 3.The code of theGetEnumDescription
method.Purpose of the Method:
- This method is used to provide human-readable descriptions for enum values.
- It's particularly useful when displaying
enum
values in a user interface or logging messages. - By decorating enum values with
DescriptionAttribute
, developers can provide meaningful descriptions that enhance the readability of the code.
- If available, this method retrieves the description associated with a given
Define the
DisplayMenu
method:- This method displays the user's menu of choices. Each option is known as acommand.
- It iterates through all the available menu choices, excluding
Unknown
, and displaying them along with their corresponding numbers. - It prompts the user to enter their selection.
- Here's a listing of my version of the
DisplayMenu
method:C#
///<summary>///Displaysthemenuofchoicesontheconsole.///</summary>///<remarks>///Thismethoditeratesthroughalltheavailablemenuchoicesanddisplaysthem///alongwiththeircorrespondingnumbers.///<para/>///Thenumberingofthechoicesstartsfrom<c>1</c>.///</remarks>privatestaticvoidDisplayMenu(){Console.WriteLine("Pleasechooseanaction:\n");varmenuItemNumber=1;foreach(MenuChoiceschoiceinEnum.GetValues(typeof(MenuChoices)))if(choice!=MenuChoices.Unknown){vardescription=GetEnumDescription(choice);Console.WriteLine($"[{menuItemNumber}]:{description}");menuItemNumber++;} Console.Write("\nEnteryourselection:");}
Listing 4.The code of theDisplayMenu
method.Purpose of the Method
- This method is called within the
Main
method to display the menu of choices to the user. - It enhances the user experience by providing a clear and organized presentation of available options.
- Presenting the choices in a numbered format helps the user easily identify and select their desired option.
- The
menuItemNumber
variable is used to display the menu item number next to each choice. - It starts from 1 to represent the first menu choice. Normally, the integer(s) associated with the member(s) of an
enum
start from zero. Starting from 1 is a better user experience. - After displaying each menu choice,
menuItemNumber++
incrementsmenuItemNumber
by 1 to move to the next menu item. - This ensures that each menu choice is displayed with a unique and sequential number, starting from 1, making it easier for the user to find and select their desired option.
Define the
Main
Method:- This is the entry point of the application.
- It contains the main application logic, including displaying the menu, getting the user's choice, and performing actions based on that choice.
- It runs in an infinite loop until the user chooses to exit the application.
- If the user chooses
Exit
, it prompts them to confirm if they are sure they want to exit. After typing their response, the user must press theENTER
key on the keyboard to confirm.- If the confirmation is affirmative (
Y
ory
), the application terminates. - If the user typesany other input, the console is cleared, and the menu is displayed again.
- This is an important cybersecurity vulnerability mitigation: doing this guards against a so-called code injection attack.
- If the confirmation is affirmative (
- After each action, it prompts the user to press any key to continue, clears the console, and displays the menu again.
- Here's a listing of my version of the
Main
method:C#
///<summary>///Theentrypointoftheapplication.///</summary>///<remarks>///Thismethodservesasthestartingpointoftheconsoleapplication.///<para/>///Itcontinuouslydisplaysamenuofchoicestotheuserandexecutesthe///correspondingactionsbasedontheirselection.///<para/>///Themenuisdisplayeduntiltheuserdecidestoexittheapplication.///</remarks>publicstaticvoidMain(){while(true){DisplayMenu();varchoice=GetUserChoice(); //Convert1-basedmenuchoiceto0-basedindexvarchoiceIndex=(int)choice-1; //Checkifchoiceiswithinthevalidrangeif(choiceIndex>=0&&choiceIndex<Enum.GetValues(typeof(MenuChoices)).Length)//Checkagainstallmenuitems//Performactionbasedonuserchoiceindexswitch(choiceIndex){case(int)MenuChoices.EatCandy:Console.WriteLine("YouchosetoEatCandy."); //AddyourEatCandylogicherebreak; case(int)MenuChoices.GoFishing:Console.WriteLine("YouchosetoGoFishing."); //AddyourGoFishinglogicherebreak; case(int)MenuChoices.PlayBasketball:Console.WriteLine("YouchosetoPlayBasketball."); //AddyourPlayBasketballlogicherebreak; case(int)MenuChoices.Exit:Console.Write("Areyousureyouwanttoexittheapplication?(Y/N):");varconfirmation=Console.ReadLine().ToUpper()[0];Console.WriteLine();if(confirmation=='Y'){Console.WriteLine("Exitingtheapplication...");return;//ExittheMainmethod} Console.Clear();continue; default:Console.WriteLine("Invalidchoice.Pleasetryagain.");break;}elseConsole.WriteLine("Invalidchoice.Pleasetryagain."); Console.WriteLine("Pressanykeytocontinue...");Console.ReadKey();Console.Clear();//Cleartheconsoleforthenextiteration}}
Listing 5.The definition of theMain
method.Purpose of the Method
- The
Main
method serves as the entry point of a C# console application. - When the application is executed, the operating system looks for the
Main
method to start the program. - All the code inside the
Main
method is executed when the application starts. - It is where the execution of the program begins.
- The
Main
method contains the main logic of the application. - It typically includes tasks such as displaying user interfaces, processing user input, and performing various actions based on user choices.
- The
Main
method often involves control flow structures such as loops (while
,for
,foreach
) and conditional statements (if
,else
,switch
) to control the flow of execution within the application. - The
Main
method is responsible for determining when the application should terminate. - It usually runs in a loop until a specific condition is met, such as the user choosing to exit the application or a certain task being completed.
- The
Main
method may also handle resource management tasks such as opening and closing files, database connections, or network connections. - Error handling code, such as
try
-catch
blocks, may also be included in theMain
method to handle exceptions that occur during the execution of the application.
Entire Program.cs
File
Here's the entire Program.cs
file with all the methods combined:
C#
usingSystem;usingSystem.ComponentModel; namespaceMenuDemo{///<summary>///Definesthebehavioroftheapplication.///</summary>publicstaticclassProgram{///<summary>///Theentrypointoftheapplication.///</summary>///<remarks>///Thismethodservesasthestartingpointoftheconsoleapplication.///<para/>///Itcontinuouslydisplaysamenuofchoicestotheuserandexecutesthe///correspondingactionsbasedontheirselection.///<para/>///Themenuisdisplayeduntiltheuserdecidestoexittheapplication.///</remarks>publicstaticvoidMain(){while(true){DisplayMenu();varchoice=GetUserChoice(); //Convert1-basedmenuchoiceto0-basedindexvarchoiceIndex=(int)choice-1; //Checkifchoiceiswithinthevalidrangeif(choiceIndex>=0&&choiceIndex<Enum.GetValues(typeof(MenuChoices)).Length)//Checkagainstallmenuitems//Performactionbasedonuserchoiceindexswitch(choiceIndex){case(int)MenuChoices.EatCandy:Console.WriteLine("YouchosetoEatCandy."); //AddyourEatCandylogicherebreak; case(int)MenuChoices.GoFishing:Console.WriteLine("YouchosetoGoFishing."); //AddyourGoFishinglogicherebreak; case(int)MenuChoices.PlayBasketball:Console.WriteLine("YouchosetoPlayBasketball."); //AddyourPlayBasketballlogicherebreak; case(int)MenuChoices.Exit:Console.Write("Areyousureyouwanttoexittheapplication?(Y/N):");varconfirmation=Console.ReadLine().ToUpper()[0];Console.WriteLine();if(confirmation=='Y'){Console.WriteLine("Exitingtheapplication...");return;//ExittheMainmethod} Console.Clear();continue; default:Console.WriteLine("Invalidchoice.Pleasetryagain.");break;}elseConsole.WriteLine("Invalidchoice.Pleasetryagain."); Console.WriteLine("Pressanykeytocontinue...");Console.ReadKey();Console.Clear();//Cleartheconsoleforthenextiteration}} ///<summary>///Displaysthemenuofchoicesontheconsole.///</summary>///<remarks>///Thismethoditeratesthroughalltheavailablemenuchoicesanddisplaysthem///alongwiththeircorrespondingnumbers.///<para/>///Thenumberingofthechoicesstartsfrom<c>1</c>.///</remarks>privatestaticvoidDisplayMenu(){Console.WriteLine("Pleasechooseanaction:\n");varmenuItemNumber=1;foreach(MenuChoiceschoiceinEnum.GetValues(typeof(MenuChoices)))if(choice!=MenuChoices.Unknown){vardescription=GetEnumDescription(choice);Console.WriteLine($"[{menuItemNumber}]:{description}");menuItemNumber++;} Console.Write("\nEnteryourselection:");} ///<summary>///Retrievesthedescriptionattributevalueassociatedwiththespecifiedenum///value.///</summary>///<paramname="value">///The<seelangword="enum"/>valueforwhichtoretrievethe///description.///</param>///<returns>///Thedescriptionassociatedwiththe<seelangword="enum"/>value,if///available;otherwise,the///stringrepresentationofthe<seelangword="enum"/>value.///</returns>///<remarks>///Thismethodretrievesthedescriptionattributevalue,ifpresent,associated///withthespecified<seelangword="enum"/>value.///<para/>///Ifnodescriptionattributeisfound,itreturnsthestringrepresentationof///the<seelangword="enum"/>value.///</remarks>privatestaticstringGetEnumDescription(Enumvalue){varfield=value.GetType().GetField(value.ToString());varattribute=(DescriptionAttribute)Attribute.GetCustomAttribute(field,typeof(DescriptionAttribute));returnattribute==null?value.ToString():attribute.Description;} ///<summary>///Readsuserinputfromtheconsoleandparsesitintoa///<seecref="T:MenuDemo.MenuChoices"/>enumerationvalue.///</summary>///<returns>///The<seecref="T:MenuDemo.MenuChoices"/>enumerationvaluecorrespondingto///theuserinput.///Iftheinputcannotbeparsedintoavalidenumerationvalue,returns///<seecref="F:MenuDemo.MenuChoices.Unknown"/>.///</returns>///<remarks>///Thismethodreadsalineoftextfromtheconsoleinputandattemptstoparse///itintoa<seecref="T:MenuDemo.MenuChoices"/>enumerationvalue.///<para/>///Iftheinputmatchesanyoftheenumerationvalues,thecorresponding///enumerationvalueisreturned.///<para/>///Iftheinputcannotbeparsedintoavalidenumerationvalue,themethod///returns<seecref="F:MenuDemo.MenuChoices.Unknown"/>.///</remarks>privatestaticMenuChoicesGetUserChoice(){varinput=Console.ReadLine();returnEnum.TryParse(input,outMenuChoiceschoice)?choice:MenuChoices.Unknown;}}}
Listing 6.The final content of our Program.cs
file.
Step 4: Running the Application
- Press
F5
on the keyboard, or click the Debugmenu on the menu bar, and then clickStart Debuggingto run the application.- Visual Studio should automatically build your application into a
.exe
file, and then launch that.exe
file for you. - What you see should resemble -- although it may not look exactly the same --Figure 1.
- Visual Studio should automatically build your application into a
- Follow the on-screen instructions to interact with the menu.
- Test each menu option and verify that the application behaves as expected.
Congratulations! You've successfully created a menu-driven console application in C# using .NET Framework 4.8. You've learned to display a menu, handle user input, and implement features like confirming actions before execution. Keep exploring and experimenting with C# to enhance your programming skills further.
Dr. Brian Hart obtained his Ph.D. in Astrophysics from the University of California, Irvine, in 2008. Under Professor David Buote, Dr. Hart researched the structure and evolution of the universe. Dr. Hart is an Astrodynamicist / Space Data Scientist with Point Solutions Group in Colorado Springs, CO, supporting Space Operations Command, United States Space Force. Dr. Hart is a Veteran of the U.S. Army and the U.S. Navy, having most recently served at Fort George G. Meade, MD, as a Naval Officer with a Cyber Warfare Engineer designator. Dr. Hart has previously held positions at Jacobs Engineering supporting Cheyenne Mountain/Space Force supporting tests, with USSPACECOM/J58 supporting operators using predictive AI/ML with Rhombus Power, and with SAIC supporting the Horizon 2 program at STARCOM. Dr. Hart is well known to the community for his over 150 technical publications and public speaking events. Originally from Minneapolis/Saint Paul, Minnesota, Dr. Hart lives in Colorado Springs with his Black Lab, Bruce, and likes bowling, winter sports, exploring, and swimming. Dr. Hart has a new movie coming out soon, a documentary called "Galaxy Clusters: Giants of the Universe," about his outer space research. The movie showcases the Chandra X-ray Observatory, one of NASA’s four great observatories and the world’s most powerful telescopes for detecting X-rays. The movie has been accepted for screening at the U.S. Air Force Academy ("USAFA" for short) Planetarium and will highlight how scientists use clusters of galaxies, the largest bound objects in the Universe, to learn more about the formation and evolution of the cosmos --- as well as the space telescopes used for this purpose, and the stories of the astronauts who launched them and the scientists who went before Dr. Hart in learning more about the nature of the Universe.