C# IConvertible Interface

Introduction

Did you know that an interface binds your class to implement the defined functionalities declared within it? I have to mention this because we are going to explore how to play with IConvertible interface. In this post, we will try to implement the IConvertible using a simple example. Let’s get started.

What is IConvertible Interface?

The IConvertible interface basically provides methods that developers can use for the conversion of different types. Once you have decided to implement this interface, you must choose the field/fields within your type to support the conversion.

The conversion takes place when you have decided to invoke the implemented methods of this interface. In addition, the behavior of this conversion converts the value(s) of the implemented type to a common language runtime type.

The common language runtime types are the following: Boolean, SByte, Byte, Int16, UInt16, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char, and String.

Enough with the definitions, let's have an example.

1. Start by creating a type. 
  1. public partial class Car {  
  2.   
  3. public string Brand { getset; }  
  4.   
  5. public string Variant { getset; }  
  6.   
  7. public bool BestSeller { getset; }  
  8.   
  9. public DateTime DateBuilt { getset; }  
  10.   
  11. public double SurfaceArea { getset; }  
  12.   
  13. public double Length { getset; }  
  14.   
  15. public double Width { getset; }  
  16.   
  17. public double Height { getset; }  
  18.   
  19. }  
As you can see, the Car type class is using a partial class keyword. One reason, for the separation of implementation of the IConvertible interface and definition of properties. 
 
2. Implement the IConvertible interface. 
  1. public partial class Car : IConvertible {  
  2.   
  3. public TypeCode GetTypeCode () {  
  4.     return TypeCode.Object;  
  5. }  
  6.   
  7. public bool ToBoolean (IFormatProvider provider) {  
  8.     return this.BestSeller;  
  9. }  
  10.   
  11. public byte ToByte (IFormatProvider provider) {  
  12.     return (byte)this.SurfaceArea;  
  13. }  
  14.   
  15. public char ToChar (IFormatProvider provider) {  
  16.   
  17.     return this.Brand[0];  
  18. }  
  19.   
  20. public DateTime ToDateTime (IFormatProvider provider) {  
  21.     return this.DateBuilt;  
  22. }  
  23.   
  24. public decimal ToDecimal (IFormatProvider provider) {  
  25.     return (decimalthis.SurfaceArea;  
  26. }  
  27.   
  28. public double ToDouble (IFormatProvider provider) {  
  29.     return this.SurfaceArea;  
  30. }  
  31.   
  32. public short ToInt16 (IFormatProvider provider) {  
  33.     return (shortthis.SurfaceArea;  
  34. }  
  35.   
  36. public int ToInt32 (IFormatProvider provider) {  
  37.     return (intthis.SurfaceArea;  
  38. }  
  39.   
  40. public long ToInt64 (IFormatProvider provider) {  
  41.     return (longthis.SurfaceArea;  
  42. }  
  43.   
  44. public sbyte ToSByte (IFormatProvider provider) {  
  45.     return Convert.ToSByte (this.SurfaceArea);  
  46. }  
  47.   
  48. public float ToSingle (IFormatProvider provider) {  
  49.     return (floatthis.SurfaceArea;  
  50. }  
  51.   
  52. public string ToString (IFormatProvider provider) {  
  53.     return $"Brand: {this.Brand} Variant: {this.Variant}";  
  54. }  
  55.   
  56. public object ToType (Type conversionType, IFormatProvider provider) {  
  57.     return Convert.ChangeType (this.SurfaceArea, conversionType);  
  58. }  
  59.   
  60. public ushort ToUInt16 (IFormatProvider provider) {  
  61.     return (ushortthis.SurfaceArea;  
  62. }  
  63.   
  64. public uint ToUInt32 (IFormatProvider provider) {  
  65.     return (uintthis.SurfaceArea;  
  66. }  
  67.   
  68. public ulong ToUInt64 (IFormatProvider provider) {  
  69.     return (ulongthis.SurfaceArea;  
  70. }  
  71.   
  72. }  
Probably you have noticed that we didn't handle the overflow-exception for some of the type conversion and just made a narrowed conversion. For instance, see the code sample below. 
  1. public byte ToByte (IFormatProvider provider) {  
  2.     return (byte)this.SurfaceArea;  
 If you are thinking of ways to handle this, please see the sample codes below.
  1. public byte ToByte(IFormatProvider provider)  
  2. {  
  3.     byte result = 0;  
  4.   
  5.     if (this.SurfaceArea >= byte.MaxValue)  
  6.     {  
  7.         result = byte.MaxValue;  
  8.     }  
  9.     else  
  10.     {  
  11.         result = (byte)this.SurfaceArea;  
  12.     }  
  13.   
  14.     return result;  
  15. }  
  1. public byte ToByte(IFormatProvider provider)  
  2. {  
  3.     try  
  4.     {  
  5.         return Convert.ToByte(this.SurfaceArea);  
  6.     }  
  7.     catch (OverflowException)  
  8.     {  
  9.         return byte.MaxValue;  
  10.     }  
  11. }  
As long as the value is within the range of byte, the above example will definitely give the expected value. However, once the value goes beyond the value, data loss is expected. In addition, we can only give the maximum value of the type. In our case, the maximum range value of a byte is 255.  
 
 3. Create a new instance of Car class and call the Convert class to examine the result of the Car class type. 
  1. [TestMethod]  
  2. public void TestMethod1()  
  3. {  
  4. var car = new Car { };  
  5.   
  6. car.Brand = "Toyota";  
  7. car.Variant = "Vios G";      
  8. car.BestSeller = true;  
  9. car.DateBuilt = DateTime.Now;  
  10. car.Height = 110;  
  11. car.Length = 52;  
  12. car.Width = 24;  
  13. car.SurfaceArea =    
  14.     (((car.Length * car.Height) * 2) +  
  15.     ((car.Width * car.Height) *  2) +  
  16.     ((car.Length * car.Width) * 2));  
  17.   
  18. bool carBool = Convert.ToBoolean(car);  
  19.   
  20. Assert.IsInstanceOfType(carBool, typeof(bool));  
  21.   
  22. Assert.IsTrue(carBool);  
  23.   
  24. DateTime carDateTime = Convert.ToDateTime(car);  
  25.   
  26. Console.WriteLine($"{carDateTime.ToShortDateString()}");  
  27.   
  28. Assert.IsInstanceOfType(carDateTime, typeof(DateTime));  
  29.   
  30. string carString = Convert.ToString(car);  
  31.   
  32. Assert.IsInstanceOfType(carString, typeof(string));  
  33.   
  34. Console.WriteLine($"{carString}");  
  35.   
  36. double carDouble = Convert.ToDouble(car);  
  37.   
  38. Assert.IsInstanceOfType(carDouble, typeof(double));  
  39.   
  40. }  
Now, it is possible for the Car type class to be converted into different types. However; the type conversion will still depend on your own implementation.
 
I hope you have enjoyed this example on how to use the IConvertible interface. Until next time, happy programming.