Have you ever got this compile time error error CS0029: Cannot implicitly convert type 'string' to 'int'
? This happens when you want to pass a string
value into an int
variable.
var count = 1;
count = "20"; //you get the error
Because C# is statically typed, it will not allow it, hence, the error.
JavaScript is dynamically typed at compile time, so it allows conversion of any type to another:
var count = 1
count = "20" // no error
Another instance where you get the error in C#:
long count = 100;
int myIntCount = count;
We can only solve this problem by converting from one type to another.
Let's talk about the main kinds of type conversion we have in C# dotnet.
- Implicit conversion: This is straightforward. No exception throw, no data lost. The conversion always succeeds. Example of this is when you are converting a small numerical type to a larger one:
int count = 30;
long numberOfCount = count;
- Explicit conversion: This is required when information might be lost in the conversion or when the conversion does not just succeed. Here, we use cast expression. An example is converting a larger numerical type to a small one:
long count = 30;
int numberOfCount = (int)count;
- User-defined conversion: This is our main topic. It is performed by writing a custom method that does the conversion implicitly or explicitly. It is done to convert a custom type to another primitive or custom type.
There are some rules to follow to get your conversion working.
- the conversion methods must be public and static
- use
implicit
andexplicit
keywords to define the kind of conversion you are implementing. As explained above, implicit conversions do not throw exception or data loss unlike explicit conversions. - The type (or class) where you have the conversion method must be either a source type or a target type of that conversion. This means if you are converting from type A to type B, the conversion can be defined in either of the two types. For conversion from a custom to primitive type, the conversion is defined in the custom type.
Let's look at an example.
public class Person
{
private readonly int age;
public Person(int age)
{
//we added a constructor so we could initialise this type with a value
//and then add a check and throw an exception.
//It is not compulsory you do this.
if (age < 16)
throw new ArgumentException("You are too young for this conversion.");
this.age = age;
}
public static implicit operator int(Person person) => person.age;
public static explicit operator Person(int age) => new Person(age);
public override string ToString() => $"I am {age} years old";
}
In the code above, we have a Person
type that we want to convert to an integer and back.
Because age
field in Person
is an integer and can be easily converted to int
without throwing an exception, we use an implicit conversion, hence,
public static implicit operator int(Person person) => person.age;
This is not true for a conversion of int
to Person
because it naturally cannot occur implicitly and it could throw an exception if the age
is less than 16
. So, we do an explicit conversion:
public static explicit operator Person(int age) => new Person(age);
Now let's test our conversion:
var person = new Person(17);
int number = person; //converting Person type to integer
Console.WriteLine(number); // output: 17
Person anotherPerson = (Person)number; //converting integer type to Person
Console.WriteLine(anotherPerson); // output: 17
That was conversion of a custom type to primitive type and back.
Now let's look at conversion of a custom type to another.
Let's add another type:
public class Employee
{
public string Name { get; set; }
public int Age { get; set; }
public static explicit operator Person(Employee employee) => new Person(employee.Age); //conversion of Employee to Person
}
There is nothing particularly different from what we explained before in this code. We are converting from Employee
to Person
, so we have a conversion method that does that, using the explicit
keyword because of an exception that could happen.
Please note that we can have this method on the Person
class.
Testing this, we have:
var employee = new Employee {
Age = 23,
Name = "John"
};
Person myEmployeePerson = (Person)employee;
Console.WriteLine(myEmployeePerson.ToString()); //output: I am 23 years old
What I enjoy about C# is its extensibility. You should make use of this every chance you get. Type conversion is one of them and it will help you write cleaner code.
You can read more about this on Microsoft docs.
Top comments (0)