User-defined Conversions: Conversion between Custom Types
Tags: csharp, dotnet, beginners, programming
Published: 2022-08-20 06:18:00

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.

```csharp
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:
```js
var count = 1
count = "20" // no error
```
Another instance where you get the error in C#:
```csharp
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:

```csharp
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:

```csharp
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` and `explicit` 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.

```csharp

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:
```csharp

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:
```csharp

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:

```csharp

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](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/user-defined-conversion-operators).