Jim
Jim

Reputation: 3665

Inline switch / case statement in C#

I am on a weird kick of seeing how few lines I can make my code. Is there a way to condense this to inline case statements?

    switch (FIZZBUZZ)
    {
      case "Fizz":
        {
          //Do one process
          break;
        }
      case "Buzz":
        {
          //Do one process
          break;
        }
      case "FizzBuzz":
        {
          //Do one process
          break;
        }
    }

to look something like this:

    switch (FIZZBUZZ)
    {
      case "Fizz": //Do one process
      case "Buzz": //Do one process
      case "FizzBuzz": //Do one process
    }

Upvotes: 33

Views: 88938

Answers (13)

GoldBishop
GoldBishop

Reputation: 2861

So I took this on as a challenge. Instead of the usual answers of "Just use Switch..Case syntax" statements, I made it a coding challenge of skill and knowledge (not that I have much of either).

Setup

Using

public enum FizzBuzz {
    Fizz,
    Buzz,
    FizzBuzz
}

public static class EnumExtension {
    public static void SwitchCase ( this FizzBuzz enm , params KeyValuePair<FizzBuzz , Action> [] parms ) {
        foreach ( var kvp in parms ) {
            if ( kvp.Key == enm ) {
                kvp.Value();
            }
        }
    }
}

Implementation

public class Program {
    static void Main ( string [] args ) {
        var enm = FizzBuzz.Fizz;

        ProcessEnum( enm );
    }

    public static void ProcessEnum ( FizzBuzz enm ) {
        enm.SwitchCase(
            new KeyValuePair<FizzBuzz , Action>( FizzBuzz.Fizz , FizzMethod ) ,
            new KeyValuePair<FizzBuzz , Action>( FizzBuzz.Buzz , BuzzMethod ) ,
            new KeyValuePair<FizzBuzz , Action>( FizzBuzz.FizzBuzz , FizzBuzzMethod )
            );
    }

    private static void FizzMethod () {
        System.Console.WriteLine( "" );
    }
    private static void BuzzMethod () {
        System.Console.WriteLine( "" );
    }
    private static void FizzBuzzMethod () {
        System.Console.WriteLine( "" );
    }

}

Upvotes: 0

Joel
Joel

Reputation: 6173

Introduced in C# 8.

You can now do switch operations like this:

FIZZBUZZ switch
{
    "fizz"     => /*do something*/,
    "fuzz"     => /*do something*/,
    "FizzBuzz" => /*do something*/,
    _ => throw new Exception("Oh ooh")
};

Assignment can be done like this:

string FIZZBUZZ = "fizz";
string result = FIZZBUZZ switch
    {
        "fizz"     => "this is fizz",
        "fuzz"     => "this is fuzz",
        "FizzBuzz" => "this is FizzBuzz",
        _ => throw new Exception("Oh ooh")
    };
Console.WriteLine($"{ result }"); // this is fizz

Function calls:

public string Fizzer()     => "this is fizz";
public string Fuzzer()     => "this is fuzz";
public string FizzBuzzer() => "this is FizzBuzz";
...
string FIZZBUZZ = "fizz";

string result = FIZZBUZZ switch
    {
        "fizz"     => Fizzer(),
        "fuzz"     => Fuzzer(),
        "FizzBuzz" => FizzBuzzer(),
        _ => throw new Exception("Oh ooh")
    };
Console.WriteLine($"{ result }"); // this is fizz

Multiple inline-actions per case (delegates are a must I think):

string FIZZBUZZ = "fizz";
string result = String.Empty;

_= (FIZZBUZZ switch
{
    "fizz" => () =>
    {
        Console.WriteLine("fizz");
        result = "fizz";
    },
    "fuzz" => () =>
    {
        Console.WriteLine("fuzz");
        result = "fuzz";
    },
    _ => new Action(() => { })
});

You can read more about the new switch case here: What's new in C# 8.0

Upvotes: 106

Andrew Shepherd
Andrew Shepherd

Reputation: 45252

A challenge is to use C#8 switch expressions

The problem is that the body of each branch is an expression, not a group of statements.

You can work around this by making each branch return an Action object.

Note the syntax: if I explicitly cast any one of the expressions to the Action type, then the compiler will implicitly cast each of the other expressions. I chose to cast the last (default) expression.

public static void Performction(string input) =>
    (
        (input) switch 
        {   
            "FIZZ" => () => Console.WriteLine("This is the fizz"),
            "BUZZ" => () => Console.WriteLine("This is the buzz"),
            "FIZZBUZZ" => () => 
                {
                    Console.WriteLine("This is a Fizz");
                    Console.WriteLine("But it is a buzz as well!");
                },
            _ => new Action(() => {})
        }
    )();

Upvotes: 0

Aleksey Pavlov
Aleksey Pavlov

Reputation: 154

In C# 8 you can do something like this

    public Form1()
    {
        InitializeComponent();
        Console.WriteLine(GetSomeString("Fizz"));
    }

    public static string GetSomeString(string FIZZBUZZ) =>
       FIZZBUZZ switch
       {
           "Fizz" => "this is Fizz",
           "Buzz" => "this is Buzz",
           "FizzBuzz" => "this is FizzBuzz",
           _ => "Unknown"
       };

This is equivalent to

    public static string GetSomeString(string FIZZBUZZ)
    {
        switch (FIZZBUZZ)
        {
            case "Fizz": return "this is Fizz";
            case "Buzz": return "this is Buzz";
            case "FizzBuzz": return "this is FizzBuzz";
            default: return "Unknown";
        }
    }

Upvotes: 7

Daniel Bodnar
Daniel Bodnar

Reputation: 370

FYI, if anyone was looking for a inline shorthand switch case statement to return a value, I found the best solution for me was to use the ternary operator multiple times:

string Season = "Spring";
Season = Season == "Fall" ? "Spring" : Season == "Spring" ? "Summer" : "Fall";

You can optionally make it more readable while still inline by wrapping it in parens:

Season = (Season == "Fall" ? "Spring" : (Season == "Spring" ? "Summer" : "Fall"));

or by using multiple lines and indenting it:

Season = Season == "Fall" ? "Spring" 
       : Season == "Spring" ? "Summer" 
       : "Fall";

So, to serve as a code execution block you could write:

string FizzBuzz = "Fizz";
FizzBuzz = FizzBuzz == "Fizz" ? MethodThatReturnsAString("Fizz") : (FizzBuzz == "Buzz" ? MethodThatReturnsAString("Buzz") : MethodThatReturnsAString("FizzBuzz"));

Not the most respectable solution for a long list of case elements, but you are trying to do an inline switch statement ;)

Critiques from the community?

Upvotes: 15

Bill W
Bill W

Reputation: 1488

I don't know of any way to do this, while maintaining some readability, other than the obvious:

switch (FIZZBUZZ) 
    { 
      case "Fizz": { //Do one process } break;
      case "Buzz": { //Do one process  } break;
      case "FizzBuzz": { //Do one process  } break;
    }

Upvotes: 0

Paul Ruane
Paul Ruane

Reputation: 38590

With the assumption that this is purely esoteric and that you will not be tempted to use this in a production system, you could abuse expression trees:

FIZZBUZZ.Switch(Fizz => DoSomething(),
                Buzz => DoSomethingElse(),
                FizzBuzz => DoSomethingElseStill());

Where Switch is an extension method:

public static void Switch(this string @this, params Expression<Action>[] cases)
{
    Expression<Action> matchingAction = cases.SingleOrDefault(@case => @case.Parameters[0].Name == @this);
    if (matchingAction == null) return; // no matching action

    matchingAction.Compile()();
}

Upvotes: 9

Andrew Hare
Andrew Hare

Reputation: 351516

If you want to condense things you could just put things on one line (let's imagine that "do one process is a call to Console.WriteLine):

switch (FIZZBUZZ)
{
    case "Fizz": Console.WriteLine("Fizz"); break;
    case "Buzz": Console.WriteLine("Buzz"); break;
    case "FizzBuzz": Console.WriteLine("FizzBuzz"); break;
}

If you want to get fancy you could create a map of strings to actions like this:

var map = new Dictionary<String, Action>
{
    { "Fizz", () => Console.WriteLine("Fizz") },
    { "Buzz", () => Console.WriteLine("Fizz") },
    { "FizzBuzz", () => Console.WriteLine("FizzBuzz") }
};

And then you could invoke the method like this:

map[FIZZBUZZ].Invoke(); // or this: map[FIZZBUZZ]();

Upvotes: 26

duraz0rz
duraz0rz

Reputation: 397

You don't need the curly braces for the case statements, but do you need a break statement for each case. Otherwise, you can't really do much

Upvotes: 0

Peter
Peter

Reputation: 1806

You can put as much code on one line as you like with C#.

As Andrew says.

Personally my preference is to leave white space as it allows easier reading of the code but then again I am the only dev here who comments his code or writes methods and functions small enough to be able to quickly scan the code to see exactly what it does. :)

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500525

Well if you're really interested in fewest lines of code you can write:

switch (FIZZBUZZ) { case "Fizz": /* Do one process */ break; case "Buzz": /* Do one process */ break; case "FizzBuzz": /* Do one process */ break; }

I wouldn't recommend it though.

It's hard to tell exactly what you're asking though - are you trying to fall through between cases, or just remove braces?

Upvotes: 1

Hans Olsson
Hans Olsson

Reputation: 55009

Well an easy way would be:

switch (FIZZBUZZ)
{
     case "Fizz": Console.WriteLine("Fizz"); break;
     case "Buzz": Console.WriteLine("Buzz"); break;
     case "FizzBuzz": Console.WriteLine("FizzBuzz"); break;
}

Which is only one line each. But there's multiple statements per line...

Upvotes: 0

Alex Krupnov
Alex Krupnov

Reputation: 460

You always have to have a break statement in order to leave the switch other than that you can do it as you mention

  switch (FIZZBUZZ)
    {
      case "Fizz": /*Do one process*/break;
      case "Buzz": /*Do one process*/break;
      case "FizzBuzz": /*Do one process*/break;
    }

Upvotes: 1

Related Questions