Aim
To read a single character from the console and classify it as an uppercase letter, a lowercase letter, or a non-alphabetic character using the char type and the Unicode-aware System.Char API.
Theory
char in C# is a 16-bit value type (System.Char) that stores a UTF-16 code unit — not a 1-byte ASCII code as in C. Because char is a struct living on the stack (or inline inside its container), classifying characters never allocates on the GC heap. Classification methods such as char.IsLetter, char.IsUpper and char.IsLower consult the Unicode category tables (Lu = Letter uppercase, Ll = Letter lowercase), so they work for 'É' as correctly as for 'A' — a naive range test like ch >= 'A' && ch <= 'Z' fails for accented letters. Console.ReadLine() returns a string (an immutable reference type); indexing it with input[0] yields a char at zero conversion cost because a string IS a read-only sequence of UTF-16 code units. The program also demonstrates the ternary conditional operator and the defensive guard string.IsNullOrWhiteSpace — protection against a null or empty line (in online runners stdin is often empty, hence the default 'A'). Note that Console.ReadLine returns null at end-of-stream, which is exactly the case the guard covers.
Requirements
- .NET SDK 8.0+ and any editor, or the built-in RUN CODE button
- CLI commands:
dotnet new console,dotnet run
Procedure
- Create the project:
dotnet new console -n CaseCheck, thencd CaseCheck. - Paste the program into
Program.cs. - Run with
dotnet run, type a character (e.g.g) and press Enter. - Re-run with
G,9and an empty line to exercise all four code paths (upper, lower, non-letter, default).
Explanation of the Code
string input = Console.ReadLine();reads one whole line; it may benullwhen the input stream is closed.char ch = string.IsNullOrWhiteSpace(input) ? 'A' : input[0];— the ternary picks the safe default 'A' when no input is supplied, otherwise takes the first UTF-16 code unit of the line.if (!char.IsLetter(ch))rejects digits, punctuation and whitespace BEFORE the case test — order matters: testingIsUpperfirst would silently misreport '9' as "lowercase" in theelsebranch.char.IsUpper(ch)checks Unicode category Lu; the finalelsetherefore means lowercase letter.$"{ch} is Uppercase."is string interpolation: the compiler lowers it tostring.Format(or the allocation-freeDefaultInterpolatedStringHandlerin .NET 6+).
Expected Output
Interactive session (typed input echoes after the prompt):
Enter a character (default A): g
g is Lowercase.
With input G → G is Uppercase.; with 7 → Not an alphabet character.; with empty input the default prints A is Uppercase.
🎯 Viva Questions
- Is
chara value or reference type? — Value type (System.Char), 16 bits wide, stored inline or on the stack. - Why prefer
char.IsUpperoverch >= 'A' && ch <= 'Z'? — It is Unicode-aware and correct for non-ASCII letters such as 'É'. - What does
Console.ReadLinereturn at end-of-stream? —null, which is why the null/whitespace guard exists. - What does string interpolation compile to? —
string.Formator an interpolated string handler;{ch}is a compile-time format hole, not a runtime text splice. - What is the Unicode category of 'A'? — Lu (Letter, uppercase).
- Why check
IsLetterbeforeIsUpper? — To route non-letters to their own branch; otherwise digits would fall into the lowercaseelse.