Controlling Type conversion in C#

You can become a serverless blackbelt. Enrol to my 4-week online workshop Production-Ready Serverless and gain hands-on experience building something from scratch using serverless technologies. At the end of the workshop, you should have a broader view of the challenges you will face as your serverless architecture matures and expands. You should also have a firm grasp on when serverless is a good fit for your system as well as common pitfalls you need to avoid. Sign up now and get 15% discount with the code yanprs15!

Ever run into a situation where your application needs to use a type for its internal working but occasionally need to convert that type into another just so it can be passed to another application which doesn’t understand some of the base types we have in the .Net space?

Consider the example below, where the Player is a type in my problem domain, but I need to communicate information about the player with a non-.Net client which doesn’t have the Guid type, so I need to have a PlayerDTO type used exclusively for message passing:

public sealed class Player
{
    public Player(string name, long score)
    {
        Name = name;
        Score = score;
        ID = Guid.NewGuid();
    }

    public string Name { get; private set; }
    public Guid ID { get; private set; }
    public long Score { get; private set; }
}

public sealed class PlayerDTO
{
    public PlayerDTO(string name, long score, string id)
    {
        Name = name;
        Score = score;
        ID = id;
    }

    public string Name { get; private set; }
    public string ID { get; private set; } // client is not .Net based so no Guid there
    public long Score { get; private set; }
}

The problem here is that there is no easy way to convert the Player type to PlayerDTO and every time I want to create a new PlayerDTO object I need to manually copy the values from Player into PlayerDTO’s constructor, and my application needs to know that it needs to convert Player.PlayerID into a string.

A cleaner solution here is to overload either the implicit or explicit converter so you can simply cast a Player object into a PlayerDTO object:

// Overload explicit cast converter to allow easy conversion from a Winner to WinnerAmfvo object
public static explicit operator PlayerDTO(Player player)
{
    return new PlayerDTO(player.Name, player.Score, player.PlayerID.ToString());
}

Further more, this allows you to easily convert an array of Player objects into an array of PlayerDTO objects:

// use Array.ConvertAll
PlayerDTO[] playerDTOs = Array.ConvertAll(players, p => (PlayerDTO) p);
// use Linq
playerDTOs = players.Select(p => (PlayerDTO) p).ToArray();

No Interface types allowed

One thing to bear in mind when using the implicit/explicit operators is that you won’t be able to use interface types, and the reason is specified in Section 10.9.3 of the C# spec.

In short, defining an implicit or explicit conversion between reference types gives the user the expectation that there will be a change in reference; after all, the same reference cannot be both types. On the other hand, the user does not have the same expectation for conversions between reference types and interface types.

In these cases, you still have other ways to make type conversion cleaner and centralised, for example:

Create a FromIPlayer method


playerDTOs = iPlayers.Select(p => PlayerDTO.FromPlayer(p)).ToArray();

Put all conversions in a PlayerConvert static object

If you have lots of types which can be converted to many types then it might be a cleaner solution to just put all the conversions into one static object, like the System.Convert class. You then use it like this:


playerDTOs = iPlayers.Select(p => PlayerConvert.ToPlayerDTO(p)).ToArray();

References:

StackOverflow question on why you can't use interface types with implicit/explicit operator
Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter


Hi, I’m Yan. I’m an AWS Serverless Hero and I help companies go faster for less by adopting serverless technologies successfully.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

Hire me.


Skill up your serverless game with this hands-on workshop.

My 4-week Production-Ready Serverless online workshop is back!

This course takes you through building a production-ready serverless web application from testing, deployment, security, all the way through to observability. The motivation for this course is to give you hands-on experience building something with serverless technologies while giving you a broader view of the challenges you will face as the architecture matures and expands.

We will start at the basics and give you a firm introduction to Lambda and all the relevant concepts and service features (including the latest announcements in 2020). And then gradually ramping up and cover a wide array of topics such as API security, testing strategies, CI/CD, secret management, and operational best practices for monitoring and troubleshooting.

If you enrol now you can also get 15% OFF with the promo code “yanprs15”.

Enrol now and SAVE 15%.


Check out my new podcast Real-World Serverless where I talk with engineers who are building amazing things with serverless technologies and discuss the real-world use cases and challenges they face. If you’re interested in what people are actually doing with serverless and what it’s really like to be working with serverless day-to-day, then this is the podcast for you.


Check out my new course, Learn you some Lambda best practice for great good! In this course, you will learn best practices for working with AWS Lambda in terms of performance, cost, security, scalability, resilience and observability. We will also cover latest features from re:Invent 2019 such as Provisioned Concurrency and Lambda Destinations. Enrol now and start learning!


Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!