eodeluga
eodeluga

Reputation: 698

How to use C# pattern matching with tuples

I'm experimenting with switch statement pattern matching, and I'm looking for a way to return false if either value in a two value tuple is zero. This is the code I'm trying:

static bool IsAnyValueZero((decimal, decimal) aTuple)
{
    switch(aTuple)
    {
        case (decimal, decimal) t when t.Item1 == 0 || t.Item2 == 0:
            return true;
    }
    return false;
}

In VSCode 1.47 and dotnetcore 3.14 I get a compile-time error:

CS8652: The feature 'type pattern' is in Preview`

What is the best compatible way to write this code?

Upvotes: 8

Views: 8042

Answers (1)

Iliar Turdushev
Iliar Turdushev

Reputation: 5213

Type pattern in C# 8 does not support matching against tuple type in the form (decimal, decimal) t. But we can match against tuple type by specifying type ValueTuple that is used to represent tuples in C#:

public static bool IsAnyValueZero((decimal, decimal) aTuple)
{
    switch (aTuple)
    {
        case ValueTuple<decimal, decimal> t when t.Item1 == 0 || t.Item2 == 0:
            return true;
    }
    return false;
}

Here is demo.


Another way to write your code is to use tuple pattern:

public static bool IsAnyValueZero((decimal, decimal) aTuple)
{
    switch (aTuple)
    {
        case (decimal i1, decimal i2) when i1 == 0 || i2 == 0:
            return true;
    }
    return false;
}

Or we can rewrite this code the next way:

public static bool IsAnyValueZero((decimal, decimal) aTuple)
{
    switch (aTuple)
    {
        // Discards (underscores) are required in C# 8. In C# 9 we will
        // be able to write this case without discards.
        // See https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/patterns3.md#type-patterns.
        case (decimal _, decimal _) t when t.Item1 == 0 || t.Item2 == 0:
            return true;
    }
    return false;
}

Also we can specify matching values explicitly:

public static bool IsAnyValueZero((decimal, decimal) aTuple)
{
    switch (aTuple)
    {
        case (0, _):
            return true;
        case (_, 0):
            return true;
    }
    return false;
}

Here is demo.


C# 9 adds improvements to type pattern so that we will be able to match against tuple type using the next syntax (as in your original code sample):

switch (aTuple)
{
    // In C# 9 discards (underscores) are not required.
    case (decimal, decimal) t when t.Item1 == 0 || t.Item2 == 0:
        return true;
}

This feature is in C# 9 preview and it can be enabled.

Upvotes: 15

Related Questions