IConvertible Interface
Overview
Enables a class to be converted to a base type such as Boolean, Byte, Double, or String.
C# allows
widening conversion without any casting, e.g.: going from int to double,
see below.
Narrowing conversion requires explicit conversion.
Overloading operators allows for implicit and explicit conversion of custom types, as
demonstrated below.
Implementing IConvertible allows the use of Convert with your custom type.
Examples
Widening conversion
int i = 1;
double d = 1.0001;
d = i; // Compiles without casting.
Narrowing Conversion
Int16 a = 1;
Int32 b = 1;
double c = 1;
a = (Int16)b; // a = b will not be allowed, narrowing!
a = (Int16)c; // a = c will not be allowed, narrowing!
b = a; // Allowed, widening
b = (Int32)c; // b = c will not be allowed, narrowing!
c = a; // Allowed, widening
c = b; // Allowed, widening
Overloading Operators
class Program
{
static void Main(string[] args)
{
MyPlaceholder a ;
int b;
// Allowed because of the 'implicit' operator
a = 5;
Console.WriteLine(a.Value);
// Allowed because of the string implicit operator,
// don't do this however!! Way to error-prone!
a = "7";
Console.WriteLine(a.Value);
// Allowed because of the 'explicit' operator
b = (int)a;
Console.WriteLine(b);
}
}
public class MyPlaceholder
{
public int Value { get; private set; }
public MyPlaceholder(int value)
{
Value = value;
}
public static implicit operator MyPlaceholder(int arg)
{
MyPlaceholder obj = new MyPlaceholder(arg);
return obj;
}
public static implicit operator MyPlaceholder(string arg)
{
MyPlaceholder obj = new MyPlaceholder(Convert.ToInt32(arg));
return obj;
}
public static explicit operator int(MyPlaceholder arg)
{
return arg.Value;
}
}
Implementing IConvertible
class Program
{
static void Main(string[] args)
{
MyPlaceholder a = new MyPlaceholder(5);
int b;
// Allowed because of the IConvertible interface
b = Convert.ToInt32(a);
Console.WriteLine(b);
// Allowed because of the IConvertible interface
Console.WriteLine(Convert.ToDouble(a));
// Not Allowed because of the InvalidCastException
Console.WriteLine(Convert.ToDateTime(a));
}
}
public class MyPlaceholder: IConvertible
{
public int Value { get; private set; }
public MyPlaceholder(int value)
{
Value = value;
}
#region IConvertible Members
public double ToDouble(IFormatProvider provider) { return Value; }
public float ToSingle(IFormatProvider provider) { return Value; }
public int ToInt32(IFormatProvider provider) { return Value; }
public long ToInt64(IFormatProvider provider) { return Value; }
public string ToString(IFormatProvider provider) { return Value.ToString(); }
public TypeCode GetTypeCode()
{
return TypeCode.Object;
}
public bool ToBoolean(IFormatProvider provider)
{
throw new InvalidCastException();
}
public byte ToByte(IFormatProvider provider)
{
throw new InvalidCastException();
}
public char ToChar(IFormatProvider provider)
{
throw new InvalidCastException();
}
public DateTime ToDateTime(IFormatProvider provider)
{
throw new InvalidCastException();
}
public decimal ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException();
}
public short ToInt16(IFormatProvider provider)
{
throw new InvalidCastException();
}
public sbyte ToSByte(IFormatProvider provider)
{
throw new InvalidCastException();
}
public object ToType(Type conversionType, IFormatProvider provider)
{
throw new InvalidCastException();
}
public ushort ToUInt16(IFormatProvider provider)
{
throw new InvalidCastException();
}
public uint ToUInt32(IFormatProvider provider)
{
throw new InvalidCastException();
}
public ulong ToUInt64(IFormatProvider provider)
{
throw new InvalidCastException();
}
#endregion
}