C# 8 Switch Expression with Multiple Cases with Same Result

C# 8 switch expression with multiple cases with same result

I got around to installing it, but I have not found a way to specify multiple, separate case labels for a single switch section with the new syntax.

However, you can create a new variable that captures the value and then use a condition to represent the cases that should have the same result:

var resultText = switchValue switch
{
var x when
x == 1 ||
x == 2 ||
x == 3 => "one to three",
4 => "four",
5 => "five",
_ => "unknown",
};

This is actually more concise if you have many cases to test, because you can test a range of values in one line:

var resultText = switchValue switch
{
var x when x > 0 && x < 4 => "one to three",
4 => "four",
5 => "five",
_ => "unknown",
};

C# 8 switch expression: Handle multiple cases at once?

As of C#9, you can do exactly what you wanted via "disjunctive or" patterns:

private static GameType UpdateGameType(GameType gameType) => gameType switch
{
GameType.RoyalBattleLegacy or GameType.RoyalBattleNew => GameType.RoyalBattle,
GameType.FfaLegacy or GameType.FfaNew => GameType.Ffa,
_ => gameType;
};

Further reading:

  • What's new in C# 9.0: pattern matching enhancements
  • Patterns C# reference

Multiple case in c# 8.0 switch expression

or operator in switch is not available in c# 8.0, it is available c# 9.0 or greater versions, in c# 8.0 you may solve as following:

static string CardinalToOrdinal(int number)
{
return number switch
{
11 => $"{ number}th",
12 => $"{ number}th",
13 => $"{ number}th",
_ => $"{number}" + number.ToString()[number.ToString().Length - 1]
switch
{
'1' => "st",
'2' => "nd",
_ => "th"
}
};
}

For more information, pls look to this article

Multiple statements in a switch expression: C# 8

Your only supported choice is the func like you did. See [this article][1] for more information. His example:

var result = operation switch
{
"+" => ((Func<int>)(() => {
Log("addition");
return a + b;
}))(),
"-" => ((Func<int>)(() => {
Log("subtraction");
return a - b;
}))(),
"/" => ((Func<int>)(() => {
Log("division");
return a / b;
}))(),
_ => throw new NotSupportedException()
};

Just because switch expressions are new doesn't mean they are the best for all use cases. They are not designed to contain multiple commands.

Edit: I suppose you could also simply call external functions instead of making anonymous ones.
[1]: https://alexatnet.com/cs8-switch-statement/

Multiple cases in switch statement

There is no syntax in C++ nor C# for the second method you mentioned.

There's nothing wrong with your first method. If however you have very big ranges, just use a series of if statements.

Multiple cases in switch statement with same alias

It rather depends on what the data type of rangeA and rangeB are.

Assuming they're object, you can do something like this. It will throw an exception at runtime if you create a Range<Something non-comparable> then call ContainsInclusive on it. You can add an extra check for that if you want, but it gets a bit messy as Nullable<T> doesn't implement any interfaces, so you'll have to resort to reflection.

public class Program
{
public static void Main()
{
Foo(new Range<int>() { ValueFrom = 1, ValueTo = 10 }, new Range<int>() { ValueFrom = 0, ValueTo = 10 });
Foo(new Range<int?>() { ValueFrom = 1, ValueTo = 10 }, new Range<int?>() { ValueFrom = 0, ValueTo = 10 });
}

private static bool Foo(object rangeA, object rangeB)
{
return (rangeA, rangeB) switch
{
(Range<int> a, Range<int> b) => b.ContainsInclusive(a),
(Range<int?> a, Range<int?> b) => b.ContainsInclusive(a),
_ => false,
};
}
}

public class Range<T>
{
public T ValueFrom { get; set; }
public T ValueTo { get; set; }

public bool ContainsInclusive(Range<T> other)
{
return Comparer<T>.Default.Compare(other.ValueFrom, this.ValueTo) <= 0 &&
Comparer<T>.Default.Compare(other.ValueTo, this.ValueFrom) >= 0;
}
}

If you can't use the new switch expressions in this way, you can potentially do something like:

private static bool Foo(object rangeA, object rangeB)
{
return TryContainsInclusive<int>(rangeA, rangeB) ||
TryContainsInclusive<int?>(rangeA, rangeB);
}

private static bool TryContainsInclusive<T>(object a, object b)
{
if (a is Range<T> rangeA && b is Range<T> rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}

return false;
}

If rangeA and rangeB can be generic types, you can get away with the simpler:

private static bool Foo<T>(Range<T> rangeA, Range<T> rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}

If rangeA and rangeB can be some base Range type, then you can do something like this. Again, this will throw at runtime if T isn't comparable:

public class Program
{
public static void Main()
{
Foo(new Range<int>() { ValueFrom = 1, ValueTo = 10 }, new Range<int>() { ValueFrom = 0, ValueTo = 10 }).Dump();
Foo(new Range<int?>() { ValueFrom = 1, ValueTo = 10 }, new Range<int?>() { ValueFrom = 0, ValueTo = 10 }).Dump();
}

private static bool Foo(Range rangeA, Range rangeB)
{
return rangeB.ContainsInclusive(rangeA);
}
}

public abstract class Range
{
public abstract bool ContainsInclusive(Range other);
}

public class Range<T> : Range
{
public T ValueFrom { get; set; }
public T ValueTo { get; set; }

public override bool ContainsInclusive(Range other)
{
if (other is Range<T> o)
{
return Comparer<T>.Default.Compare(o.ValueFrom, this.ValueTo) <= 0 &&
Comparer<T>.Default.Compare(o.ValueTo, this.ValueFrom) >= 0;
}

return false;
}
}

Using blocks in C# switch expression?

however I didn't understand where this is addressed in the documentation

This is stated pretty clear here:

There are several syntax improvements here:

  • The variable comes before the switch keyword. The different order makes it visually easy to distinguish the switch expression from the
    switch statement.
  • The case and : elements are replaced with =>. It's more concise and intuitive.
  • The default case is replaced with a _ discard.
  • The bodies are expressions, not statements.

{ someDir.Delete(); ... MoreActions} is not an expression.

However, you can abuse every feature, as they say :)

You can make the switch expression evaluate to an Action, and invoke that action:

Action a = response switch
{
"yes" => () => { ... },
_ => () => { .... }
};
a();

You can even reduce this to a single statement:

(response switch
{
"yes" => (Action)(() => { ... }),
_ => () => { ... }
})();

But just don't do this...



Related Topics



Leave a reply



Submit