Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 240
eodeluga Avatar asked Aug 25 '20 15:08

eodeluga


People also ask

How is C used?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What does || mean in C?

The logical OR operator ( || ) returns the boolean value true if either or both operands is true and returns false otherwise.


1 Answers

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.

like image 115
Iliar Turdushev Avatar answered Oct 08 '22 22:10

Iliar Turdushev