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":
开发者_如何学Python {
//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
}
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
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]();
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?
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()();
}
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";
}
}
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;
}
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?
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...
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. :)
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
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;
}
Necromancer poster here
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 .net-4.5.2
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( "" );
}
}
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(() => {})
}
)();
精彩评论