Once again, I have to pick on pointers as an example. When you had a pointer in C++, you were free to cast it to any type, including doing rather idiotic things such as casting an int* (int pointer) to a double* (double pointer). As long as memory backed that operation, it kind of "worked." This is not the kind of type safety you would envision for an enterprise-level programming language.

Because of the outlined problems, C# implements strictest type safety to protect itself and the garbage collector. Therefore, you must abide by a few rules in C# with regard to variables:
·         You cannot use uninitialized variables. For member variables of an object, the compiler takes care of zeroing them. For local variables, you are incharge. However, if you use an uninitialized variable, the compiler will tell you so. The advantage is that you get rid of those errors when using an uninitialized variable to compute a result and you don't know how these funny results are produced.
·         C# does away with unsafe casts. You cannot cast from an integer to a reference type (object, for example), and when you downcast, C# verifies that this cast is okay. (That is, that the derived object is really derived from the class to which you are down casting it.)
·         Bounds checking is part of C#. It is no longer possible to use that "extra" array element n, when the array actually has n-1 elements. This makes it impossible to overwrite unallocated memory.
·         Arithmetic operations could overflow the range of the result data type. C# allows you to check for overflow in such operations on either an application level or a statement level. With overflow checking enabled, an exception is thrown when an overflow happens.
·         Reference parameters that are passed in C# are type-safe.