Advertisements
Posted by: jsonmez | January 20, 2013

Implicit and Explicit Conversion Operators in C#

Recently I stumbled upon a pretty interesting feature of C# that I either neglected to really pay attention to before or just had entirely missed.

It is definitely debatable whether or not one should even use this feature, because it is likely to result in some confusing situations by someone reading your code even if they are aware of the feature’s existence.

Take a look at this code

Let’s look at an example that might look a bit strange.

What would you think if you stumbled upon this code?

Book book = new Book("Code Complete");
XDocument document = book;

 

new book

What if I told you that Book does not inherit from XDocument?

In this case a custom implicit casting is happening because of an implicit conversion operator I created on Book.

Here is how it is defined:

public class Book
{
        private readonly string title;

        public Book(string title)
        {
            this.title = title;
        }

        public static implicit operator XDocument(Book b)
        {
            // Code to convert the book into an XML structure
            return new XDocument();
        }

        protected List<Page> Pages { private get; set; }
}

 

What is happening in this case is that the compiler is noticing that I am trying to assign a Book object to a variable of type XDocument and that I have defined an implicit operator to allow that conversion.

By defining this implicit conversion operator I can assign any Book to an XDocument and it will execute the code defined in my implicit operator method to return an XDocument.

Backwards as well

I can also make the conversion the other way.

XDocument document = new XDocument();
Book book = (Book)document;

 

You can see here that I am doing something a bit different though.  In this case I am explicitly casting the XDocument into a Book.

I could have used implicit conversion, like the previous example, but not all XDocuments can automatically be converted to Books, so I wanted to make it allowed only if someone explicitly used the casting operator to perform the cast.

Here is what that code looks like:

 public static explicit operator Book(XDocument d)
{
	 // Code to convert the XML document into a book
    return new Book("");
}

 

Limitations

You can only use the implicit and explicit operators on classes that you have defined.  You can’t use them to extend existing classes to add automatic conversions.

Also the conversions can’t chain automatically.  If you have a conversion to type a Dog to a Cat and a Cat to a Mouse, you can’t assign a Dog directly to a Mouse.

Should I use it?

Now that is a tough question.  I have some mixed thoughts on actually using this feature.

My biggest problem with it is the discoverability.  When I look at code that is assigning a Book to an XDocument, I don’t immediately know where to look for the code that is allowing that assignment.  The code could actually exist in either the Book class or the XDocument class.  (We happen to know in this case that XDocument is a .NET class, so it’s not going to be there, but where you have to user defined classes, you can’t be sure.)

If I didn’t know about implicit and explicit operator overloads, I would be even more puzzled.

My other reservation is that in most cases it is not immediately obvious what exactly is happening.

  • Are we getting a copy of Book that is representing an XML structure?
  • Are we getting a raw XML document that could be populated with Book data?
  • Are we losing data here?

I can look at the method to figure out what is going on, but that makes the code that is using the implicit or explicit conversion less readable by itself.

It seems to me in that case having a method off of Book called ToXDocument() would make things at least a bit more clear.

On the other hand, I can definitely see some benefits to using these operators to make code more succinct and to make types that have obvious conversion easier to work with.

Consider having classes that represent temperatures in Celsius and Fahrenheit.  In those cases implicit conversion operators between the two formats makes intuitive sense.  We can also be pretty confident that the conversion would not result in a data loss.

termo

General guidelines

In general, my recommendation would be to avoid defining implicit and explicit operators because it is likely that most developers reading your code will be confused by them and in most cases you are not adding much value.

I would say that you should only use implicit and explicit operators when the conversion between two types is very clear because they are just different ways of representing the same value.

Although I can see the cases for other uses of the operators, it seems like there the usage is more likely to cause confusion than bring clarity.

To me an equal sign means assignment, I do not often think of it to mean conversion.

I could of course be wrong about my thoughts on implicit and explicit operators, but as of yet I haven’t seen it in the wild, so if you have some good examples of where it makes sense to use this feature, please let me now.

If you like this post don’t forget to Follow @jsonmez or subscribe to my RSS feed.

Advertisements

Responses

  1. Interesting article. Haven’t come through this feature before.

    Although it makes the code less readable, it cuts some overwork recasting types in the project.

    I think if used in a private project where developers know what is happening, it will help make the code better.

  2. I’ve used this a few times in internal libraries. The situation is where the library wants a custom type, but the common usage is providing a single value (strings).

    To me, it makes the developer usage easier (no wrapping in a custom type) but they are free to use the abstraction directly to provide some rare setting. The library can sit wholly with the abstraction.

    • That makes sense. Like if I had a library that took a special wrapped string that had a value for the EOL style called EOLAwareString and I created a conversion operator to convert from string to the EOLAwareString. Then I would pretty much just use strings and not explicitly wrap all my strings unless I actually needed to change the EOL setting.

  3. I’m a bit surprised you missed it. It’s only useful in certain situations, but it’s extremely useful.

    By the way, if you’re already doing an explicit conversions, other conversions may be tacked on automatically, so there is some chaining. See here: http://blogs.msdn.com/b/ericlippert/archive/2007/04/16/chained-user-defined-explicit-conversions-in-c.aspx

    • Ah. I didn’t realize that. Thanks for the link. Yeah, not sure why I missed it for so long. I guess it was just something I glossed over and then never really used or saw used anywhere.

  4. I often use this feature with construction builder classes;
    Book myBook = new BookBuilder().Title(“..”).Author(“..”);

  5. […] Implicit and Explicit Conversion Operators in C# (John Sonmez) […]

  6. Sometimes another interesting example is refactoring Primitive Obsession. For example if have an ID that I pass around the system as an integer. Then I decide I want to make an entity to wrap the primitive in order to encapsulate validation rules and logic on that ID. Implicit casting can be handy to introduce a limited refactor where the Entity ID can implicitly accept int assignment or be used in contexts needing an int.

    With this approach new code can use validated entities rather than primitives and yet still be compatible with primitives. Could do the same with other “obsessed” primitives e.g. telephone numbers passed around as strings replaced by a Telephone entity with validation logic.

    • Good example. That make sense.

  7. I got into conversion operators back when I was killing my primitive obsession[1][2]. I got some great ground rules from Jimmy Bogard’s post on ZipCode String conversions[3]. And Phil Haack took that and ran with it[4]. Great post, brings in Skeet/Lippert and talks about a specific use case in WPF data binding.

    This is the implementation in .NET of a must have skill. And one that I found “leaky”. If you don’t practice and study killing primitive obsession, you’ll lose your knack for it!

    [1]: http://www.anthonymastrean.com/blog/primitive-disinterest/
    [2]: http://www.anthonymastrean.com/blog/primitive-disinterest-advanced-semantics/
    [3]: http://lostechies.com/jimmybogard/2007/12/03/dealing-with-primitive-obsession/
    [4]: http://haacked.com/archive/2012/09/30/primitive-obsession-custom-string-types-and-self-referencing-generic-constraints.aspx

    • Thank you sir, awesome links. I was thinking about doing a post like the primitive disinterest one. Great stuff!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: