NDepend Blog

Improve your .NET code quality with NDepend

New C#9 keywords ‘and’ ‘or’ ‘not’

October 5, 2020 4 minutes read

HoweverThe C#9 language introduces new controversial keywords:

  • and keyword: Conjunctive patterns. Require both patterns to match
  • or keyword: Disjunctive patterns. Require either pattern to match
  • not keyword: Negative patterns. Require that a pattern doesn’t match

In this article we’ll explore how some common expressions can be rewritten with these keywords and how they improve the pattern matching syntax. We’ll question also the motivations beside these keywords and their impact on code complexity.

(and or not) vs. (&& || !)

With those new keywords it is now possible to write C# code similar to what we have with VB or F#. For example:

Clearly the first implementation is more expressive and concise. It relies on patterns over the parameter c which is then mentioned only once. The second impl relies on boolean expressions: each expression needs its own mention of c which makes this usual approach less concise.

However, for a developer that uses C C++ C# for over 30 years the first implementation hurts.  Moreover we now have 2  different syntaxes to achieve the same implementation.

This new syntax looks like the VB one. In March 2020 Microsoft announced: We Do Not Plan to Evolve Visual Basic as a Language. Did Microsoft choose to add those keywords now to onboard more VB.NET developers to C#? I didn’t find any explicit resource on the web but this would make sense.

Show me the IL code generated

A good habit when dealing with new C# syntactic sugar is to look at IL generated by the compiler. The IL implementations of our two expressions are quite similar. However the new syntax generates more IL branch instructions and a local variable. At least this analysis confirms that this is just syntactic sugar. There is no magic – like new dedicated IL instructions – happening behind our back.

C#9 and or keywords decompiled
C#9 ‘and’ ‘or’ keywords decompiled

Pattern Matching Improvement

As guessed, pleasing VB developers certainly weighted in the balance for this new syntax. But pattern matching enhancement might have been the primary goal as this 2018 C# language discussion suggests. A common usage looks like:

But since patterns are evaluated with order of declaration and that all integer values are covered by our switch, this example doesn’t need the new and keyword. It can be rewritten to:

The initial example based on character sets isolated in the range of all possible characters makes more sense to illustrate this syntax enhancement:

Multiple variables definitions

Now several variables can be defined in a pattern expression:

But as soon as not or or is used, variable definition is not permitted:

C#9 multiple variables pattern not possible with 'not' or 'or' keywords
C#9 multiple variables pattern not possible with ‘not’ or ‘or’ keywords

Or usage

As long as there is no variable definition the keyword or can be used in typing expressions like:

Usage with tuples

The keyword or is useful especially with tuples comparison:

This gets compiled to:

Multiple variables definitions and tuples

Mixing tuples with multiple variable definitions with the keyword and is possible. This can lead to weird scenarios:

This really means:

  • If the tuple (obj1,obj2) satisfies pattern1 and pattern2.
  • Refined to: if the tuple (obj1,obj2) satisfies (obj1 is 0) and (obj2 is an int) and (obj1 is an int) and (obj2 is 0).

Not very readable and useful indeed!

Here is a more decent and comprehensive usage:

Note that you cannot declare a variable more than once:

"<yoastmark

Other common usages

Here are some common usages of these new keywords. As stated in the first section, VB and F# programmers will be pleased but it hurts my C# programmer sensibility.

A useless (but common) sample for this new feature is if(myBool is true or false). This expression is quite different than if(myBool is true || false) which can be read: (if myBool equals true then return true) else (return false).

A better example is the expression if(x is 1 or 2 or 3). It is more compact than if((x==1) || (x==2) || (x==3)) and makes sense.

Also we can bet that expressions like if(myString is not null) or if(x is not Person) will become popular.

Impact on Cyclomatic Complexity

In terms of code complexity it is clear that the new keywords and and  or are equivalent to && and  ||. This is why the next NDepend version will take account of these new keywords in its algorithm to estimate the Source Code Cyclomatic Complexity. It already takes account of those expressions:

We will release the upcoming NDepend version hopefully this month of October 2020 with full support for .NET 5.0, C#9, Blazor and much more.

Conclusion

C# now proposes 3 sets of 3 boolean operators.

  • & | !: Boolean operators over bits
  • && || !: Boolean operators over bool
  • and or not: Boolean operators over patterns

Certainly Microsoft added the last set to both please F# and VB programmers and improve the pattern matching syntax. On legacy code I’d recommend keeping their usage to tricky pattern matching expression only. I wouldn’t like enjoy in a code base that relies on various syntax facilities to express the same thing.

Comments:

  1. Marcel Popescu says:

    Nitpick: in VolumeDiscountPercentage1, the cases for 3 and 6 are not handled; the VolumeDiscountPercentage2 method is not equivalent.

  2. Patrick Smacchia says:

    Fixed thanks!

  3. I’m sure I’ll use all of these patterns over time, but right now I’m just happy to write “x is not null” instead of “!(is is null)” or “x is {}”

  4. i like it.
    slowly taking over visual basic / python syntax
    🙂

  5. Jerry Carpenter says:

    Wow! C# is looking more like COBOL everyday.

  6. Nicely explained. Thank you.

Comments are closed.