Implicit vs Explicit Conversion in C#
We use implicit and explicit conversion in C# all the time, without even realizing it. Let's learn more about them and look at examples of each.
If you’ve programmed in C# for awhile, you’ve likely used both implicit and explicit conversion without even realizing it. Let's take a look at examples of each.
Implicit Conversion of .NET Data Types
Consider an example. A Decimal
is capable of storing any Int32
value, without losing any information about the number the integer represents. So we're allowed to define an integer and then store it in a decimal without the compiler yelling at us. The conversion from integer to decimal is implicit:
int quantity = 5;
decimal amount = quantity; // no problemo
What if we go the opposite direction though?
decimal amount = 5;
int quantity = amount; // compiler: "Cannot implicitly convert type 'decimal' to 'int'"
This is disallowed, because we run the risk of losing information about the Decimal
, which can store a fraction as well as a much larger value than Int32
. The compiler is saving us from ourselves, since we may not realize we’re potentially losing data.
Even though we can’t implicitly convert a Decimal
to an Int32
, we can still explicitly convert the values:
decimal quantity = 5;
int quantity2 = (int)quantity; // whatever, cast away!
The (int)
cast here is forcing the conversion, in essence telling the compiler, “Yes, I know the risks, convert it anyway.”
decimal quantity = 5;
int quantity2 = (int)quantity; // whatever, cast away!
There's a variety of reasons you might need to do this, but the important thing is that you can.
Implicit Conversion in Our Own Types
The implicit and explicit conversion operators allow us to implement conversiosn in our own types. Here's what Microsoft has to say on the implicit
operator (emphasis mine) (note: this verbiage seems to have been removed since the time this article was written, but it's still relevant and important):
By eliminating unnecessary casts, implicit conversions can improve source code readability. However, because implicit conversions do not require programmers to explicitly cast from one type to the other, care must be taken to prevent unexpected results. In general, implicit conversion operators should never throw exceptions and never lose information so that they can be used safely without the programmer’s awareness. If a conversion operator cannot meet those criteria, it should be marked explicit.
In other words, we can use the implicit keyword to hide the exact details of the conversion from others, but don't do something like allowing a decimal to be converted to an integer implicitly and then just silently dropping the fractional portion.
Let's look at some examples.
Example 1 – Implicitly Convert String to Person
Imagine we have a Person
class with an implicit
operator defined on it:
public class Person(string name)
{
private readonly string _name = name;
/// <summary>
/// Implicitly convert a string to a new Person.
/// </summary>
/// <param name="name"></param>
public static implicit operator Person(string name)
{
return new Person(name);
}
}
We'd normally instantiate the class like this:
Person person = new Person("Bob");
But thanks to the implicit
conversion defined, we could also do this:
Person person = "Mary";
That gives us a new Person
with the name set to "Mary".
Example 2 – Implicitly Convert DateTime to Birthday
Now imagine we have a Birthday
class with its own implicit
operator:
public class Birthday(DateTime birthday)
{
private readonly DateTime _birthday = birthday;
/// <summary>
/// Implicitly convert a DateTime to a new Birthday.
/// </summary>
/// <param name="birthday"></param>
public static implicit operator Birthday(DateTime birthday)
{
return new Birthday(birthday);
}
}
Similar to the Person
class, we can just pass it a DateTime
and get a new Birthday
:
Birthday birthday = new DateTime(1970, 6, 2);
What if we wanted to convert a Birthday
back to a DateTime
for some reason? We could define another implicit
operator, but doing that might go against the general guidance that implicit conversions shouldn't lose data.
Instead, we could create an explicit
operator:
public static explicit operator DateTime(Birthday birthday)
{
return birthday._birthday;
}
Using it means that anyone using our code needs to explicitly convert a Birthday
to the desired type.
DateTime birthdate = (DateTime)birthday;
If they don't cast it, the compiler throws an error:
Final Thoughts
Being able to define our own implicit and explicit conversions is a powerful tool for .NET developers, but it should be used carefully. In particular, if there's any chance of data loss, use an explicit
conversion instead of an implicit
one.
One other caveat – there’s no intellisense when using a conversion operator, so any “summary” comment you add above the keyword will go unnoticed and unread by whoever's using your class. Don't depend on someone dipping into your code to see if there's any gotchas or side-effects in your conversions!
If you want to learn more, there's a programming guide from Microsoft titled Casting and Type Conversions that might be interesting.
Spread the Word