Implicit operators. There be dragons!

Here is a cool geek bar game:

Can you write an implicit cast operator on the back of a napkin without looking up the csharp reference?

Let’s give it a try:

class Foo {
   public static implicit operator string(Foo foo) {
      return foo.someMember;
    }
   }

You will probably never believe me that I was able to “just type it out”. So all hope is lost for me 😉

CSharp supports both explicit and implicit conversation operators. They have their purpose but in my opinion, you should almost always try to avoid implicit conversation operators. They are black magic and sometimes pure evil unless you really now what you are doing. Suppose you have the following code:

static string input = new EntityAddress("foo");

static bool Compare(EntityAddress address) {
   return input != address;
}

It is pretty hard in code reviews to spot what is happening here. Can you see it?

The code above tells us that there is an implicit conversation of EntityAddress to string because we can magically assign a new instance of EntityAddress to a string. The following code makes this possible:

public class EntityAddress {
   private string value;

   public EntityAddress(string value) {
      this.value = value;
      // parse value and assign to properties
   }

   public static implicit operator string(EntityAddress ad) {
      return ad.value;
   }
}

But the Compare method accepts an instance of an EntityAddress. So which comparison will be used for the != operator?

Well since we have an implicit conversation to string the left side of the operator is the field input which is of type string. Therefore EntityAddress will be implicitly converted to string as well and the != operator for string comparisons is used. Luckily in my trivial example, I used strings and a reference type. Naturally, the compiler would not allow me to compile this code without the implicit operators. But imagine what could go wrong when you compare reference type to reference type with implicit conversation potentially combined with faulty equality comparison. I won’t even try to imagine how long it would take me to spot that error. If you work in projects with simple minds like me, then I suggest you keep the code simple and convert it explicitly to the types you need like:

static bool Compare(EntityAddress address) {
   return input.ToString() != address.ToString();
}

Don’t use black magic like implicit conversations. Just don’t.

About the author

Daniel Marbach

Add comment

Recent Posts