Switch on a tuple

Bob
Bob in C#
using System.Linq;

public static class Bob
{
    private static bool IsShout(string input) => input.Any(c => char.IsLetter(c)) && input.ToUpper() == input;

    public static string Response(string statement)
    {
        var input = statement.TrimEnd();
        if (input == "")
            return "Fine. Be that way!";

        switch ((input.EndsWith('?'), IsShout(input)))
        {
            case (true, true): return "Calm down, I know what I'm doing!";
            case (_, true): return "Whoa, chill out!";
            case (true, _): return "Sure.";
            default: return "Whatever."; 
        }
    }
}

In this approach you use a switch to test if there is a question or a shout. The switch returns the right response for a question, shout, shouted question, or for not being a shout or question.

The String TrimEnd method is applied to the input to eliminate any whitespace at the end of the input. If the string has no characters left, it returns the response for saying nothing.

Caution

Note that a null string would be different from a string of all whitespace. A null string would throw an Exception if TrimEnd were applied to it. To test a string that might be null or only whitespace, the IsNullOrWhiteSpace method of String would be used.

Next a tuple is made from the conditions for a queston and a shout. The first half of the shout condition

input.Any(c => char.IsLetter(c)) && input.ToUpper() == input

is constructed from the Any LINQ method and the IsLetter Char method to ensure there is at least one letter character in the String. This is because the second half of the condition tests that the uppercased input is the same as the input. If the input were only "123" it would equal itself uppercased, but without letters it would not be a shout.

The tuple is tested in a switch. It checks the values of the expressions in the tuple, and uses the _ discard pattern to disregard a value. If none of the patterns match, the default arm of the switch returns the response when the input is neither a question nor a shout.

Shortening

When the body of an if statement is a single line, both the test expression and the body could be put on the same line, like so

if (input == "") return "Fine. Be that way!";

The C# Coding Conventions advise to write only one statement per line in the layout conventions section, but the conventions begin by saying you can use them or adapt them to your needs. Your team may choose to overrule them.

For Any, the lambda expression of c => char.IsLetter(c) can be shortened to just the method call of char.IsLetter like so

input.Any(char.IsLetter)

Any passes a single character in each iteration, and the char.IsLetter method is called on that character implicitly. There is a detailed description of how it works in the accepted answer for this StackOverflow question.

8th May 2024 · Found it useful?