Simplify Your Code with Pattern Matching: Type Tests in C#

Pattern Matching

Introduction:

Pattern matching in C# is a powerful feature that simplifies common programming patterns and enables you to perform type tests and extract values from objects in a clear and brief way. In this blog post, you will explore the concept of type tests in pattern matching and demonstrate how they can simplify your code. Let's dive in!

Understanding Type Tests in Pattern Matching:

Type tests in pattern matching involve checking if an object is of a particular type and then extracting and working with the object in a type-safe manner. This eliminates the need for explicit casting and provides a more readable and maintainable solution. Let's illustrate this with an example:

// Base shape class
class Shape { }

// Circle class
class Circle : Shape
{
    public double Radius { getset; }
}

// Rectangle class
class Rectangle : Shape
{
    public double Width { getset; }
    public double Height { getset; }
}

// Triangle class
class Triangle : Shape
{
    public double Base { getset; }
    public double Height { getset; }
}

class Program
{
    static void Main(string[] args)
    {
        Shape shape1 = new Circle { Radius = 5.0 };
        Shape shape2 = new Rectangle { Width = 3.0Height = 4.0 };
        Shape shape3 = new Triangle { Base = 6.0Height = 2.5 };
        Shape shape4 = new Shape();

        ProcessShape(shape1);
        ProcessShape(shape2);
        ProcessShape(shape3);
        ProcessShape(shape4);
    }

    static void ProcessShape(Shape shape)
    {
        if (shape is Circle circle)
        {
            // Shape is a Circle, and we can work with it using the `circle` variable of type Circle
            double area = Math.PI * Math.Pow(circle.Radius2);
            Console.WriteLine($"Area of the circle: {area}");
        }
        else if (shape is Rectangle rectangle)
        {
            // Shape is a Rectangle, and we can work with it using the `rectangle` variable of type Rectangle
            double area = rectangle.Width * rectangle.Height;
            Console.WriteLine($"Area of the rectangle: {area}");
        }
        else if (shape is Triangle triangle)
        {
            // Shape is a Triangle, and we can work with it using the `triangle` variable of type Triangle
            double area = 0.5 * triangle.Base * triangle.Height;
            Console.WriteLine($"Area of the triangle: {area}");
        }
        else
        {
            // Shape is not any of the known types
            Console.WriteLine("Unknown shape");
        }
    }
}

Shape Hierarchy:

  • The Shape class serves as the base class for all shapes.
  • The Circle class inherits from the Shape class and adds a Radius property to represent the circle's radius.
  • The Rectangle class also inherits from Shape and includes Width and Height properties to define the dimensions of the rectangle.
  • The Triangle class, again derived from Shape, has a Base and Height property to specify the base length and height of the triangle.

Main Method:

  • Inside the Main method, several shape objects are created and assigned to variables: shape1, shape2, shape3, and shape4.
  • shape1 represents a circle with a radius of 5.0, shape2 represents a rectangle with width 3.0 and height 4.0,shape3 represents a triangle with base 6.0 and height 2.5.
  • shape4 is an instance of the base Shape class.

Processing the Shapes:

  • The ProcessShape method is called for each shape object to perform specific operations based on the object's type.
  • Depending on the type of the shape (Circle, Rectangle, or Triangle), the method calculates and displays the corresponding area.
  • If the shape is of an unknown type (not Circle, Rectangle, or Triangle), a message is displayed indicating it is an unknown shape.

Output of the Code Sample: When you execute the code snippet provided, you get the following output:

Area of the circle: 78.53981633974483
Area of the rectangle: 12
Area of the triangle: 7.5
Unknown shape

This output demonstrates the pattern matching and type tests in action. The code accurately calculates and displays the areas of the different shapes based on their specific properties. It correctly identifies the circle, rectangle, and triangle objects and performs the corresponding calculations. In the case of an unknown shape, it handles the situation by indicating it as an unknown shape.

Benefits of Type Tests in Pattern Matching:

Readability: Pattern matching enhances code readability by clearly expressing different cases based on object types. The code becomes self-explanatory and easier to understand, even for newcomers to the codebase.

Maintainability: With pattern matching, handling different object types becomes more easy to understand and organized in one place. If new types are added in the future, it's easy to extend the pattern matching logic, reducing the chances of errors and increasing code maintainability.

Type Safety: Pattern matching ensures type safety within each block. When working with a specific object type, you can access its properties and methods without the risk of runtime errors. The compiler verifies the correctness of the type inference.

Conclusion:

Pattern matching with type tests in C# simplifies your code by providing a clear and concise way to handle different object types. By eliminating the need for explicit casting and introducing type safety, your code becomes more readable, maintainable, and less prone to errors.

In this blog post, you explored how to use type tests in pattern matching through a practical example. However, type tests are just one aspect of pattern matching. C# offers various other patterns like constant patterns, relational patterns, and more, which allow you to match and work with values based on specific patterns or conditions.

I hope you found it informative and helpful. If you have any questions or feedback, feel free to leave a comment below. Happy coding!

Comments

Popular posts from this blog

Entity Framework Core (EF) with SQL Server LocalDB

Exploring EventCallback in Blazor: Building Interactive Components

A Step-by-Step Guide to Implementing Identity in ASP.NET Core MVC