Help with KeyboardUtility class

WB1975

Well-known member
Joined
Apr 3, 2020
Messages
87
Programming Experience
Beginner
I thought it might be a good idea to have a class that handles all the keyboard stuff so i dont have to keep writing input code over and over i mean thats one of the pros i read about OOP, reusable code.

I have created a Class called KeyboardUtility and I have it returning number only input when the function is called.

I'm just wondering if im on the right track as usual, or whether this should be done another way.

I only have one function, but want to add like 1 to 4 menu, or y / n question or letters only etc etc

any ideas/advice would be accepted with arms wide open!!!

C#:
using System;
using System.Collections.Generic;
using System.Text;

namespace FootballLeague
{
    class KeyboardUtility
    {

        public static int NumberOnlyInput(string askForNumbers)
        {
            bool finishedEnteringNumbers = false;
            string userInput;
            int userNumberReturned;

            while (!finishedEnteringNumbers)
            {
                Console.WriteLine(askForNumbers);
                userInput = Console.ReadLine();
                bool isNumeric = int.TryParse(userInput, out userNumberReturned);
                if (isNumeric)
                {
                    return userNumberReturned;
                }
                else
                    {
                        Console.WriteLine("That is not a valid number...");
                    }
            }
            return 0;
        }
    }
}
 
I have added 2 more methods to this class for a menu system, 1 just prints it and the other handles the logic, again would appreciate any feedback, thanks guys.

C#:
public static void PrintMenu()
        {
            Console.WriteLine("\n\tMenu");
            Console.WriteLine("\t****");
            Console.WriteLine("\n\t1 - do something");
            Console.WriteLine("\t2 - do something");
            Console.WriteLine("\t3 - do something");
            Console.WriteLine("\t4 - do something");
            Console.WriteLine("\t5 - do something");
            Console.WriteLine("\t(q/Q)uit");
        }

and...

C#:
public static void MenuLogic()
        {
            bool selectionMade = false;
            while (!selectionMade)
            {
                char ch = Console.ReadKey(true).KeyChar;
                ch = char.ToUpper(ch);
                switch (ch)
                {
                    case '1':
                        Console.WriteLine("func 1");
                        selectionMade = true;
                        break;
                    case '2':
                        Console.WriteLine("func 2");
                        selectionMade = true;
                        break;
                    case '3':
                        Console.WriteLine("func 3");
                        selectionMade = true;
                        break;
                    case '4':
                        Console.WriteLine("func 4");
                        selectionMade = true;
                        break;
                    case '5':
                        Console.WriteLine("func 5");
                        selectionMade = true;
                        break;
                    case 'Q':
                        Console.WriteLine("Quit");
                        selectionMade = true;
                        break;
                }
            }
        }
 
Well that print menu and menu logic utility is not going to be very useful because you would have to copy and paste it or re-write it for each time you need a new menu. In other words, you have tight cohesion and tight coupling.

This is why I said in the other thread that I usually end up writing a menu utility which let's me pass in the menu options and returns to me which choice the user made. The utility is data driven so nothing is hardcoded within it. This is an application of the tight cohesion, loose coupling programming principle.
 
Yes I would love to make something like that....you dont have something "lying around" I could have a look at?...please...

So would your "Menu" be a separate class? meaning you wouldnt put it in a ConsoleManager class.
 
I added another method to this class called GetInt32MinMax

It will only take an int in within a coded range min and max number

is it tidy enough or is there anything I can do to make it more efficient?

thanks as always

C#:
public static int GetInt32MinMax(string prompt, int minNumber, int maxNumber)
        {
            Console.WriteLine(prompt);

            var isValid = int.TryParse(Console.ReadLine(), out var number);
            bool correctRange = false;
            
            while (!isValid || !correctRange)
            {
                {
                    Console.WriteLine("Please enter a valid number.");
                    Console.WriteLine(prompt);

                    isValid = int.TryParse(Console.ReadLine(), out number);
                    correctRange = number >= minNumber && number <= maxNumber;
                }
            }
            return number; 
        }
 
C#:
public static int GetInt32MinMax(string prompt, int minNumber, int maxNumber)
{
    Console.WriteLine(prompt);

    int number;

    while (!int.TryParse(Console.ReadLine(), out number) || number < minNumber || number > maxNumber)
    {
        Console.WriteLine("Please enter a valid number.");
        Console.WriteLine(prompt);
    }

    return number;
}
 
Lately, I've been deriving joy from the local functions C# feature. I tend to use it to help with self-documenting code.
C#:
public static int GetInt32MinMax(string prompt, int minNumber, int maxNumber)
{
    Console.WriteLine(prompt);

    int number;

    while (!(int.TryParse(Console.ReadLine(), out number) && IsInRange()))
    {
        Console.WriteLine("Please enter a valid number.");
        Console.WriteLine(prompt);
    }

    return number;
    
    bool IsInRange() => minNumber <= number && number <= maxNumber;
}

I prefer to see range checks in this form: minNumber <= number && number <= maxNumber because it's what I grew up in all my algebra classes: lowerBound <= x <= upperBound.

Also there is the best practice of trying to keep bools "positive" rather than negative, and hence the check for "is in range", rather than "is not in range".

Of course with just the refactoring to use [il]IsInRange()[/il], the while condition would have looked like:
C#:
!int.TryParse(Console.ReadLine(), out number) || !IsInRange()
The multiple !, as well as having the ! right in front of the I's and after the || just didn't make for quick visual parsing. So applying DeMorgan's Law gets the equivalent:
C#:
!(int.TryParse(Console.ReadLine(), out number) && IsInRange())

and in the end reads nicely: "while not try parse the line read into a number and it is in range", as compared to the original "while not try parse the line read into a number or the number is less than the minimum or the number is greater than the maximum".
 
please explain this line a little more

bool IsInRange() => minNumber <= number && number <= maxNumber;

isInRange? () is that a function? never seen that applied to a bool before...sigh
 
please explain this line a little more

bool IsInRange() => minNumber <= number && number <= maxNumber;

isInRange? () is that a function? never seen that applied to a bool before...sigh
Yes, it is a function. As @Skydiver said, it's a local function, i.e. a function whose scope is another function. Because it is within the other function, it can see the local variables declared in that outer function, which saves on passing parameters.

The => indicates an expression body, i.e. a function that is nothing but a return statement. That code is shorthand for this:
C#:
bool IsInRange()
{
    return minNumber <= number && number <= maxNumber;   
}
 
The => indicates an expression body, i.e. a function that is nothing but a return statement.
That is the case for a function with a return type but, for void functions, its a single line of code. It's much like you can have value Lambdas and action Lambdas.
 
Back
Top Bottom