Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the restrictions of the pattern matching mechanics?

Tags:

c#

c#-7.0

Personally, I only know that dynamic cannot be used in pattern matching which is considered a pity :(

dynamic foo = 10;
switch(foo) {
    case int i:
    break;
}

Also, valued tuple/neo-tuples cannot be used in pattern matching:

dynamic foo = (420, 360);
switch(foo) {
    case (int, int) i:
    break;
}

It was removed in current version of C#7 and was assigned for future usage.

What are the other things I cannot do?

like image 555
Steve Fan Avatar asked Feb 03 '17 05:02

Steve Fan


Video Answer


1 Answers

The new pattern matching features in C# 7 consist of the following:

  • Support for type switching,
  • Simple use of var patterns,
  • The addition of when guards to case statements,
  • the x is T y pattern expression.

Your examples focus on the first of these. And type switching is likely to be the most popular and commonly used of these new features. Whilst there are limitations, such as those that you mention, other features can be used to work around many of them.

For example, your first limitation is easily solved by boxing foo to object:

dynamic foo = 10;
switch ((object)foo)
{
    case int i:
        Console.WriteLine("int");
        break;
    default:
        Console.WriteLine("other");
        break;
}

Will print int as expected.

The var pattern and a guard can be used to work around your second restriction:

dynamic foo = (420, 360);
switch (foo)
{
    case var ii when ii.GetType() == typeof((int, int)):
        Console.WriteLine("(int,int)");
        break;
    default:
        Console.WriteLine("other");
        break;
}

will print (int,int).

Additionally, value tuples can be used for type switching, you just have to use the long-hand syntax:

var foo = (420, 360);
switch (foo)
{
    case ValueTuple<int,int> x:
        Console.WriteLine($"({x.Item1},{x.Item2})");
        break;
    default:
        Console.WriteLine("other");
        break;
}

The above will print (420,360).

For me, personally, the biggest restriction to pattern matching in C# 7 is the lack of pattern matching expressions using the match keyword. Originally, the following was planned for this release, but was pulled due to time constraints:

var x = 1;
var y = x match (
    case int _ : "int",
    case * : "other"
);

This can be worked around using switch, but it's messy:

var x = 1;
var y = IntOrOther(x);

...

private string IntOrOther(int i)
{
    switch (i)
    {
        case int _ : return "int";
        default: return "other";
    }
}

But help is at hand here with numerous 3rd party pattern matching libraries, such as my own Succinc<T> library, which let's you write it as:

var x = 1;
var y = x.TypeMatch().To<string>()
         .Caseof<int>().Do("int")
         .Else("other")
         .Result();

It's not as good as having the match keyword, but it's an optional workaround until that feature appears in a later language release.

To really understand the restrictions imposed by C# 7, it's worth referring to the the pattern matching spec on GitHub and comparing that with what will be in the next release of C#. Looking at it though, it becomes apparent that there are work-arounds to all of these.

This question was originally closed because it's open-ended as currently phrased. To give a couple of silly examples, restrictions to C# 7's pattern matching are that it won't make you a perfect cup of coffee, or fly you across the world in seconds ... but I prefer to answer the spirit of the question. And the answer really is that the only restriction is your imagination. If you don't let that restrict you, then one must take into account the fact that the work-arounds have readability and/or performance implications. They are likely the only real-world restrictions.

like image 151
David Arno Avatar answered Sep 24 '22 07:09

David Arno