BT

Pattern Matching in C# 6 and VB 12

by Jonathan Allen on Aug 14, 2014 |

Another concept from functional programming languages making its way to C# and VB is what’s known as pattern matching. At first glance pattern matching looks like a switch/select block, but it is much more powerful.

Note: Since the VB version of the specification isn’t available yet, many of these examples are from C# pattern matching specification.

The is or Matches operator

At the core of .NET’s pattern matching support is the “is/Matches” operator. This rather unusual operator breaks down a class into its constituent parts. Here is an example based on the Cartesian record class from Tuesday’s report.

public static bool operator is(Cartesian c, out double x, out double y)
    x = c.X;
    y = c.Y;
    return true;
}

This operator is not just limited to the owning type. Here is an example of defining the operator in a way that allows it to decompose a Cartesian object as if it were a Polar object.

public static class Polar {
    public static bool operator is( Cartesian c, out double R, out double Theta)
   {
        R = Math.Sqrt(c.X*c.X + c.Y*c.Y);
        Theta = Math.Atan2(c.Y, c.X);
        return c.X != 0 || c.Y != 0;
   }
}
var c = Cartesian(3, 4);
if (c is Polar(var R, *))
   Console.WriteLine(R);

Type Patterns

The simplest pattern is the Type pattern, which is essentially a try-cast with assignment. Here is an example:

if (expr is Type v)
   { // code using v }

Recursive Pattern

Most patterns are going to be recursive. That is to say, they are made up of other, often simpler, patterns. Consider this example:

var a = new Location(1, 2, 3); //x=1, y=2, z=3
if (a is Location(1, var y, *))

This is a recursive pattern consisting of a constant pattern, and var pattern, and a wildcard pattern.

Constant Pattern

This is when a match is made between a property and a constant value. Constant patterns use object.Equals(left, right) to see if there is a match.

Var Pattern

The var pattern is always considered a match. The associated variable is populated with the value coming from the is operator. The type of this variable is the statically defined type of the expression.

Wildcard Pattern

The wildcard pattern is essentially the var pattern, except you don’t care about the result.

Under the hood

Continuing with our location example, the steps the compiler takes will resemble this:

  1. Create variables $x, $y, and $z
  2. Call Location.is(a, out $x, out $y, out $z) and verify it returns true
  3. Constant Pattern: Check that object.Equals($x, 1)
  4. Var Pattern: Set y = $y
  5. Wildcard Pattern: Ignore $z

Switch/Select Case Blocks

Switch blocks will be extended to use pattern matching. Essentially this means you can write statements such as:


case null:
case String s
case Location(1, var y, *):

Limitations

Under the current draft specification, there is no support for range checks. This means you cannot write patterns such as “a is Location( > 0, 1 to 5, <= 10)”. Nor is there support for matching elements in a list or enumeration.

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Nice, but what's the use? by Dennis Doomen

So what would be the practical value of this functionality?

It's so complicated by mohammad reza moattar

I'm sure that would be very helpful but I don't understand why they're always used to be complex.

Re: It's so complicated by Faisal Waris

Pattern matching already exists in F# and I have to tell you that its is extremely useful and greatly simplifies code. You have to wrap your mind around it a bit at first.

Anders Hejlsberg - the designer for C# - has stated that F# is an inspiration for C#. Many F# features such as async/await and now immutable objects & pattern matching are being adopted by C#.

All of this is good but I believe its better to just to learn F# because it is cleaner, safer and more consistent.

Re: Nice, but what's the use? by Jonathan Allen

Just having switch statements that understood null and types would be a great help for me on day to day projects.

The more advanced features such as recursive patterns are probably going to be limited to people doing tricky stuff with deep class hierarchies such as parsing tokens in a compiler.

Re: It's so complicated by mohammad reza moattar

I'm sure it will be. I'm not talking about usefulness, All I'm trying to say is the syntax is too far complex and I know what was the source of idea.
The naming style for immutable object (record) doesn't fit to c# language and they tried to keep it because it's similar to functional languages but It doesn't make sense.

Pattern matching seems very powerful with a lots of language level facilities that we always wanted but pattern matching seems like a hitting two thing with one ball with no separation of responsibility in it. It shouldn't be a problem in functional languages but I guess it doesn't fit in c#.

Useful but has a bit of a "bolted on" feel by Patrick Quinon

This is a useful addition, but nowhere near as useful as it is in F# and other functional languages that have had such a feature from the very beginning. In F#, pattern matching is pervasive and can be used with tuples, records, lists, arrays, discriminated unions and even exception handling.

One side benefit will be bringing the idea of pattern matching to the wider programming community, for a feature that has largely been only available in functional languages. I've always had trouble showing the benefits of pattern matching in F# to C# programmers, as it is such a foreign concept. So perhaps this will have a "gateway drug" effect to prompt more .Net developers to investigate F#, which has much more powerful pattern matching capabilities and is implemented in a far more elegant manner.

It's understandable that more advanced features will bolted on to C# with the Roslyn project now completed. The danger is that C# will go down the C++ route adding more and more features, just because they can, in an attempt to appear to "stay current".

Re: Useful but has a bit of a "bolted on" feel by Jonathan Allen

I believe that the Is operator will be added to the Tuple class.

Pattern matching should work just fine with error handling. Especially now that C# is going to support filtered exceptions.

List and arrays are being considered, but I suspect that they won't make the first drop.

Re: Nice, but what's the use? by Jonathan Allen

I've been thinking about this some more and the #1 use of it for me would probably be EventArgs. Most subclasses of EventArg are essentially a Record and I can see myself using pattern matching in the event handler.

Re: Nice, but what's the use? by Patrick Quinon

A good place to start, when wondering where pattern matching can be useful, is to look at how it's used in F#, OCaml, ML and Haskell. ML has had pattern matching since the early 1980s.

Re: Nice, but what's the use? by Faisal Waris

I would like to add that F# also has Active Patterns which is a way of wrapping arbitrary functions so that they work with the pattern match syntax.

msdn.microsoft.com/en-us/library/dd233248.aspx

With Active Patterns pattern matching can be generalized; the resulting code reads better and is more understandable.

Re: It's so complicated by Vince Pan

Yes but F# got it's features and ideas from languages before it. They all stand on each others shoulders.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

11 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2014 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT