public static void CastingDemo() { // putting a more-specifically-typed value in a more generally-typed container IOutputter o = new Outputter(); // upcasting HelperMethod(new Outputter()); // upcasting // upcasting is safe, implicit (you don't have to cast with () ) Outputter o2 = (Outputter)o; // downcasting // because the compiler can't know for sure that this will work, // C# says, you have to declare your certainty that it should work with () operater. // if you were wrong, it will throw an exception at runtime. // downcasting is explicit // other kinds of casting, like numeric conversions. double x = 5.5; int a = (int)x; // int can't represent every possible double, so data could be lost if we want this to happen // (it doesn't round-to-nearest-integer, it truncates, discards the decimal places) double y = a; // double can represent every possible int, so this is safe, so it's an implicit conversion // boxing and unboxing // value types behave in one way when you pass them to a new variable (copy the value) // reference types behave in a different way (copy the reference) int x2 = 3; object o3 = x2; // the value is wrapped in a object on the heap, so that o3 can have the reference-type semantics we expect. // that's called boxing. int y2 = (int)o3; // unboxing the value. // C# supports operator overloading // you can make your class work with +, ==, [], etc // you can even define your own custom implicit casts and explicit casts. }
public static void HelperMethod(IOutputter o) { Outputter o2 = (Outputter)o; // downcasting }