5 Uncommon C# Statements/Keywords

After digging around in C#, I found some interesting discoveries. In today's post, I go over these uncommon C# statements/keywords with some examples.

Written by Jonathan "JD" Danylko • Last Updated: • Develop •
Image of Magnifying glass looking at a city

With C# 8.0 coming soon, I decided to dig into C# and look at some interesting statements and/or keywords developers have forgotten about or don't use anymore.

For today's post, I wanted to bring them to the surface and see if anyone still uses them.

While these statements/keywords are definitely rare, I can't remember the last time I've used them.

Oh, and just because I mention them here doesn't mean you can run rampant writing goto statements everywhere! ;-)

GOTO

Who doesn't remember Goto?

Goto sends the program's execution to a labeled piece of code (and no, not line numbers).

Goto statements can be applied to a switch statement or with a label.

Here is one example:

class SwitchTest
{
    static void Main()
    {
        Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");

        Console.Write("Please enter your selection: ");         string s = Console.ReadLine();
        int n = int.Parse(s);         int cost = 0;
        switch (n)         {             case 1:                 cost += 25;                 break;             case 2:                 cost += 25;                 goto case 1;             case 3:                 cost += 50;                 goto case 1;             default:                 Console.WriteLine("Invalid selection.");                 break;         }
        if (cost != 0)         {             Console.WriteLine("Please insert {0} cents.", cost);         }
        Console.WriteLine("Thank you for your business.");         // Keep the console open in debug mode.         Console.WriteLine("Press any key to exit.");         Console.ReadKey();     } } /* Sample Input:  2   Sample Output: Coffee sizes: 1=Small 2=Medium 3=Large Please enter your selection: 2 Please insert 50 cents. Thank you for your business. */

The GOTO statement has been around for a while...and not just in C#, but other various languages in general. For example, I remember writing BASIC code on my Commodore VIC-20 using GOTO statements.

Man, things have changed, but, honestly, I don't miss the GOTO statement.

Now if I see it in a program, I scratch my head and ask "why is it there?"

Checked/Unchecked

This was an interesting find.

The checked block is meant to explicitly enable overflow checking for integral-type arithmetic operations and conversions where the unchecked block is meant to suppress or prevent overflow-checking.

An example would look like this:

// Checked block.
checked
{
    int i3 = 2147483647 + ten;
    Console.WriteLine(i3);
}

Personally, I've never gone past the limits of an integer type to even warrant a checked/unchecked block, but that doesn't mean it won't happen in the future.

When

Now THIS is a versatile little statement.

You can use this in two ways:

  1. In the case label of a switch statement
  2. In the catch statement of a a try..catch exception block

In the case of an exception, this example catches a number of Http Status Codes thanks to when.

class Program
{
    static void Main()
    {
        Console.WriteLine(MakeRequest().Result);
    }

    public static async Task<string> MakeRequest()     {          var client = new System.Net.Http.HttpClient();         var streamTask = client.GetStringAsync("https://localHost:10000");         try {             var responseText = await streamTask;             return responseText;         }          catch (HttpRequestException e) when (e.Message.Contains("301")) {             return "Site Moved";         }         catch (HttpRequestException e) when (e.Message.Contains("404")) {             return "Page Not Found";         }         catch (HttpRequestException e) {             return e.Message;         }     } }

With multiple errors in an HttpRequestException, you really don't know what error occurred. This is where the when clause makes sense and saves space.

When it comes to a case statement, the when clause makes your code even more readable.

private static void ShowShapeInfo(Object obj)
{
    switch (obj)
    {
        case Shape shape when shape.Area == 0:
            Console.WriteLine($"The shape: {shape.GetType().Name} with no dimensions");
            break;
        case Rectangle r when r.Area > 0:
            Console.WriteLine("Information about the rectangle:");
            Console.WriteLine($"   Dimensions: {r.Length} x {r.Width}");
            Console.WriteLine($"   Area: {r.Area}");
            break;
        case Square sq when sq.Area > 0:
            Console.WriteLine("Information about the square:");
            Console.WriteLine($"   Length of a side: {sq.Side}");
            Console.WriteLine($"   Area: {sq.Area}");
            break;
        case Shape shape:
            Console.WriteLine($"A {shape.GetType().Name} shape");
            break;
        case null:
            Console.WriteLine($"The {nameof(obj)} variable is uninitialized.");
            break;
        default:
            Console.WriteLine($"The {nameof(obj)} variable does not represent a Shape.");
            break;   
    }
}

This gives you an expanded syntax to properly hit your case statements under the proper conditions.

Explicit/Implicit

Again, never knew these existed.

The explicit keyword is meant for declaring a user-defined type conversion operator that must be invoked with a cast.

The example is a better way to define it.

    struct Digit
    {
        byte value;
        public Digit(byte value)
        {
            if (value > 9)
            {
                throw new ArgumentException();
            }
            this.value = value;
        }

        // Define explicit byte-to-Digit conversion operator:         public static explicit operator Digit(byte b)         {             Digit d = new Digit(b);             Console.WriteLine("conversion occurred");             return d;         }     }
    class ExplicitTest     {         static void Main()         {             try             {                 byte b = 3;                 Digit d = (Digit)b; // explicit conversion             }             catch (Exception e)             {                 Console.WriteLine("{0} Exception caught.", e);             }         }     } /* Output: conversion occurred */

The implicit keyword declares an implicit user-defined type conversion operator (again, an example may clear things up).

class Digit
{
    public Digit(double d) { val = d; }
    public double val;
    // ...other members

    // User-defined conversion from Digit to double     public static implicit operator double(Digit d)     {         return d.val;     }

    //  User-defined conversion from double to Digit     public static implicit operator Digit(double d)     {         return new Digit(d);     } }
class
 Program {     static void Main(string[] args)     {         Digit dig = new Digit(7);
        //This call invokes the implicit "double" operator         double num = dig;
        //This call invokes the implicit "Digit" operator         Digit dig2 = 12;
        Console.WriteLine("num = {0} dig2 = {1}", num, dig2.val);         Console.ReadLine();     } }

Of course, these only work on operators and I ask you...when did you need the ability to code custom operators?

Yeah...I thought so. ;-)

Extern Alias

Let's say you have to reference two versions of assemblies that use the same fully-qualified type names with two or more versions of an assembly in the same app.

By using an external assembly alias, those namespaces from each assembly can be wrapped inside a root-level namespaces names by the alias where they can be used n the same file.

Based on their example, you have two grids in your application. One uses an old version (grid.dll) and one uses the new version (grid20.dll). When you compile your code, on one assembly, use the /r compiler flag:

/r:GridV1=grid.dll

and on the other assembly, use the /r flag to identify that grid.

/r:GridV2=grid20.dll

Once these are in place, you can access them through your code by adding the extern alias keyword:

extern alias GridV1

extern alias GridV2

This allows you to version your code, but still keep them separated from each other.

Conclusion

These five statements/keywords may be buried under a pile of C# code and not used as much, but C# continues to impress me with the amount of language changes it delivers to developers making it extremely flexible and competitive with the latest languages out there.

It makes me wonder what's coming next for C#.

Do you use any of these keywords or statements? Did I miss any rare gems in C#? Post your comments below and let's discuss!

ASP.NET 8 Best Practices on Amazon

ASP.NET 8 Best Practices by Jonathan Danylko


Reviewed as a "comprehensive guide" and a "roadmap to excellence" with over 120 Best Practices for ASP.NET Core 8, Jonathan's first book by Packt Publishing explores proven techniques for every phase of the SDLC.

Learn industry-standard concepts to improve your coding, debugging, and deployment of ASP.NET Core websites.

Order now on Amazon.com button

Picture of Jonathan "JD" Danylko

Jonathan "JD" Danylko is an author, web architect, and entrepreneur who's been programming for over 30 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus