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 too 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
}
You May Also Like

Exam 70-536 Study Notes
My study notes for Microsoft exam 70-536: .NET types, collections, generics, I/O, serialization and more, with C# examples.

Starting Exam 70-536 Study
After a burnout, I'm putting my own project on hold to study for Microsoft exam 70-536.

Design Patterns - Proxy Pattern
The Proxy Pattern, and the last article in the design patterns series, now that I've finished reading Head First Design Patterns.




