C# implicit user-defined type conversion

C# has a very nice little feature named implicit user-defined type conversion. By far not every developer knows about its existence because its application is very limited. However, sometimes it can be very handy to help you increasing the readability of the code by removing unnecessary clutter.
For example, you have to write many functions, which take double[ ][ ], transform it in some way and return double[ ][ ]. Very soon you will want to extract low-level operations on double[ ][ ] into separate class Matrix. Something like this:

class Matrix
{
    private readonly double[][] _m;

    public Matrix(double[][] m)
    {
        _m = m;
    }
    public Matrix Transpond()
    {
        return new Matrix(
            _m
            .First()
            .Select((sink, i) => _m.Select(row => row.ElementAt(i)).ToArray())
            .ToArray());
    }

    public Matrix Map(Func<double, double> map)
    {
        return new Matrix(
            _m
            .Select(vector => vector.Select(map).ToArray())
            .ToArray());
    }

    public double[][] ToJaggedArray()
    {
        return _m;
    }
}

All valuable methods in Matrix class return transformed Matrix. It is done to enable chaining matrix methods. Here is usage of the Matrix class:

class Program
{
    static void Main()
    {
        var m = new[]
        {
           new[] {1.0, 2.0},
           new[] {3.0, 4.0}
        };
        Print(m);
        Print(Transform(m));
    }

    public static double[][] Transform(double[][] m)
    {
        // As you can see, it is possible to chain method calls
        // And also you have to call ToJaggedArray() method
        return new Matrix(m)
            .Transpond()
            .Map(x => x * 100)
            .ToJaggedArray();
    }

    static public void Print(double[][] m)
    {
        foreach (double[] row in m)
        {
            foreach (double cell in row)
            {
                //New C# 6 feature, named Interpolated Strings
                Console.Write($"{cell} ");
            }
            Console.WriteLine();
        }
        Console.WriteLine();
    }
}

Note the call to ToJaggedArray method to be able to return from Transform method. You have to write it over and over again in every method like Transform. But conceptually double[ ][ ] and Matrix type are the same things! It would be nice to have seamless conversion from one type to another. And C# gives a tool to do this. Let’s add one more method to Matrix class:

class Matrix
{
    ...

    public static implicit operator double[][](Matrix m)
    {
        return m.ToJaggedArray();
    }
}

This weird syntax is implicit user-defined type conversion. It basically says to execute this code every time user tries to assign Matrix object to the reference of type double[ ][ ]. Now it is legal to rewrite the Transform method in the following way:

class Program
{
    ...
    public static double[][] Transform(double[][] m)
    {
        //Legal to return Matrix even though return type is double[][]
        return new Matrix(m)
            .Transpond()
            .Map(x => x * 100); 
    }
    ...
}

This same trick can be done in unit tests which use Builder pattern. It spares you from calling Build() method every time you want to get final product from your builder.

Be cautious, though. This tool as every other tool can be abused. You should not apply it to convert logically unrelated things, like getting the driver from the car. Such a code would be extremely confusing:

var car = new Car();
Driver d = car;

Sometimes you would also like to be able to write something like this:

Matrix m = new double[][]{...};

Such things could be done using extension methods if they supported implicit conversion syntaxis. But they don’t. Hence, you can’t make this expression legal, at least for now (in C#6 as well).

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

Leave a Reply

Your email address will not be published.