DEV Community

Cover image for C# conversions: Implicit VS Explicit
ByteHide
ByteHide

Posted on • Edited on • Originally published at bytehide.com

C# conversions: Implicit VS Explicit

After many years programming in .NET, you may have already realized that the framework allows us, in a very simple way, to make conversions between different types of data.

Conversions can be of 2 types 👇

  • Implicit Conversions
  • Explicit Conversions

Implicit conversions are for which it is not necessary to indicate the conversion in parentheses (…).

double variable = 10;
Enter fullscreen mode Exit fullscreen mode

In the code we assign a variable of type double a value of type int:

But the compiler doesn’t tell us anything and lets us continue working as if nothing had happened. This is known as an implicit conversion.

Instead, if we do the following 👇

int variable = 10.0;
Enter fullscreen mode Exit fullscreen mode

The compiler will give us an error indicating that an implicit conversion from double to int cannot be done, and tells us to use an explicit conversion

There is no mystery about it, simply this problem can be fixed by putting (int) in front of 10.0 👇

int variable = (int) 10.0;
Enter fullscreen mode Exit fullscreen mode

Placing the type of data to which we want to convert it in parentheses is called explicit conversion. What this means is that with this syntax we are explicitly indicating to the compiler that we want to convert one type of data into a different one.

At this point you could perfectly tell me that this would also work 👇

double variable = (double) 10;
Enter fullscreen mode Exit fullscreen mode

Apparently it does the same as if we don’t put (double) in front of it.

So… where is the difference? 🤔

The only difference between implicit and explicit conversions has to do with whether or not there is a risk of that information being lost.

If we go to the first case (without parentheses), it is an implicit conversion. The value of the litetal int does not matter as if we write double since there will be no risk of losing the information as it is a type of greater capacity.

On the contrary, if we go to the second case, we are forced to do an explicit conversion. This works because a double object can contain values ​​that a smaller capacity int type cannot represent.

Let’s take an example 👇

int variable = (int) 10.5;
Enter fullscreen mode Exit fullscreen mode

An integer type cannot contain decimals, so it will truncate 10.5 to 10, thus losing information.


How we can create our own conversions

Usually the conversions of the Framework are more than enough for the needs that arise. However, there may be many cases where it would be more useful to define our own implicit and explicit conversions. The .NET platform provides us with an easy way to do it.

To create a conversion between two types, we simply have to write the corresponding operator, either implicit or explicit.

We are going to create an imaginary scenario in which we have to manage the temperatures so that the degrees can change between Celsius and Fahrenheit.

Let’s create the code 👇

class Temperature
  {
    public float Degrees { get; set; }
  }
class Celsius : Temperature
  {
    public Celsius(float temp)
    {
      Grados = temp;
    }
  }
  class Fahrenheit : Temperature
    {
      public Fahrenheit(float temp)
    {
    Grados = temp;
    }  
  }
Enter fullscreen mode Exit fullscreen mode

Now with this code we have the possibility of writing methods so that we do the conversion between them, and which we call each time.

class Temperature
{
  public float Degrees { get; set; }
  public Celsius ToCelsius()
  {
    return new Celsius(((5.0f / 9.0f) * (this.Degrees - 32)));
  }
  public Fahrenheit ToFahrenheit()
  {
    return new Fahrenheit(((9.0f / 5.0f) * this.Degrees + 32));
  }
}
Celsius cel = new Celsius(10);
Fahrenheit far = cel.ToFahrenheit();
Celsius cel2 = far.ToCelsius();
Enter fullscreen mode Exit fullscreen mode

This works, but we will have to call the corresponding method each time and this makes the code very messy.

If we want to do an implicit conversion, we simply have to define a static operator with the static implicit operator.

We go back to our example 👇

class Temperature
  {
    public float Degrees { get; set; }
  }
  class Celsius : Temperature
  {
  public Celsius(float temp)
  {
    Grados = temp;
  }
  public static implicit operator Fahrenheit(Celsius c)
    {
      return new Fahrenheit((9.0f / 5.0f) * c.Degrees + 32);
    }
  }
  class Fahrenheit : Temperature
  {
    public Fahrenheit(float temp)
    {
      Grados = temp;
    }
  public static implicit operator Celsius(Fahrenheit fahr)
  {
  return new Celsius((5.0f / 9.0f) * (fahr.Degrees - 32));
  }
}
Celsius cel = new Celsius(10);
Fahrenheit far = cel;
Celsius cel2 = far;
Enter fullscreen mode Exit fullscreen mode

We can see that to each class we add an implicit conversion operator for the other related class, and after that, we just implicitly perform the conversions.

What we gain from this is a much cleaner code that meets the conditions for implicit conversions.


If we want to do it differently… 🤔

Let’s imagine that we have an application that has to manage the teachers and students of a school.

Let’s see it better 👇

public class Person
  {
    public string Name { get; set; }
  }
  public class Pupil : Person
  {
    public string Class{ get; set; }
    public List<int> IdsCourse { get; set; }
  }
  public class Teacher : Person
  {
    public string Class { get; set; }
    public int IdContract { get; set; }
  }
Enter fullscreen mode Exit fullscreen mode

If at some point a student becomes a teacher or vice versa, we will need to use a conversion to reuse the data. As in this case, we are going to lose information since the different classes do not handle the same information.

Therefore the conversion will have to be explicit 👇

public class Person
{
public string Name { get; set; }
}
public class Pupil : Person
{
public string Class { get; set; }
public List<int> IdsCourse { get; set; }
public static explicit operator Teacher(Pupil alum)
{
return new Teacher{ Name = alum.Name, Class= alum.Class, IdContract = -1 };
}
}
public class Teacher: Person
{
public string Class{ get; set; }
public int IdContract { get; set; }
public static explicit operator Pupil (Teacher prof)
{
return new Pupil{ Name = prof.Name, Class= prof.Class, IdsCourse = new List<int>() };
}
}
Teacher teacher = new Teacher { Name = "Juan", Class= "Programming", IdContract = 10 };
Pupil student = (Pupil)teacher;
Teacher teacher2 = (Teacher)student;
Enter fullscreen mode Exit fullscreen mode

✅ Conclution:

Marking a conversion as implicit or explicit must strictly meet the criteria of whether there is a risk of information loss. It may be the case that today you consider the loss of information that occurs to be negligible, but that at some point it is not.

If you have marked the conversion as implicit, anyone who uses it directly assumes that there is no information loss.

If there is later and the failure is in that conversion, it can be a big headache, even more so if the code is part of a library and the person who uses it cannot see the code, so always think about it before defining the conversion. 🤗

Top comments (0)