This is part 4 in a series of articles.
In this series we’ve already covered switch expressions and one little-known feature is the ability to nest switch expressions.
Suppose we have the following 3 classes:
class SavingsAccount
{
    public decimal Balance { get; set; }
}
class HomeLoanAccount
{
    public int MonthsRemaining { get; set; }
}
class ChequingAccount
{
    public decimal NumberOfTimesOverdrawn { get; set; }
    public int NumberOfAccountHolders { get; set; }
}
(Notice that none of the preceding classes are linked by inheritance.)
Suppose we wanted to run a gift card promotional mailing depending on what accounts customers had. We can use pattern matching on the type of object in a switch expression:
decimal CalculatePromotionalGiftCardValue(object account) => account switch
{
    SavingsAccount sa when (sa.Balance > 10_000) => 100,
    SavingsAccount _ => 0, // all other savings accounts
    HomeLoanAccount hla when (hla.MonthsRemaining < 12) => 20,
    HomeLoanAccount _ => 0, // all other home loan accounts
    ChequingAccount ca when (ca.NumberOfTimesOverdrawn == 0 && ca.NumberOfAccountHolders == 1) => 20,
    ChequingAccount ca when (ca.NumberOfTimesOverdrawn == 0 && ca.NumberOfAccountHolders == 2) => 40,
    ChequingAccount ca when (ca.NumberOfTimesOverdrawn == 0 && ca.NumberOfAccountHolders == 3) => 50,
    ChequingAccount _ => 0, // all other chequing accounts
    { } => throw new ArgumentException("Unknown account type", paramName: nameof(account)), // all other non-null object types
    null => throw new ArgumentNullException(nameof(account))
};
Notice in the preceding expression-bodied method containing a switch expression (that’s a mouthful!), that there is a bit of repetition in the ChequingAccount section with the ca.NumberOfTimesOverdrawn == 0 code being repeated. We can replace this section with a nested switch expression:
decimal CalculatePromotionalGiftCardValueNested(object account) => account switch
{
    SavingsAccount sa when (sa.Balance > 10_000) => 100,
    SavingsAccount _ => 0,
    HomeLoanAccount hla when (hla.MonthsRemaining < 12) => 20,
    HomeLoanAccount _ => 0,
    ChequingAccount ca when (ca.NumberOfTimesOverdrawn == 0) => ca.NumberOfAccountHolders switch
    {
        1 => 20,
        2 => 40,
        3 => 50,
        _ => 0
    },
    ChequingAccount _ => 0,
    { } => throw new ArgumentException("Unknown account type", paramName: nameof(account)),
    null => throw new ArgumentNullException(nameof(account))
};
If you want to fill in the gaps in your C# knowledge be sure to check out my C# Tips and Traps training course from Pluralsight – get started with a free trial.


		
		
	
		SHARE: