#953 – Static Typing vs. Dynamic Typing

C# enforces type safety in that it limits you to interacting with an object in ways that are allowed by that object’s type.

C# achieves type safety through the use of both static typing and dynamic typing.  (Also referred to as “static type-checking” and “dynamic type-checking”).

Static typing is the process of enforcing type safety at compile-time.  The compiler prohibits certain operations, based on the type of the objects involved.

For example:

Cat c = new Cat("Fluffy");
c.Bark();

At compile-time, the compiler flags an error when we try to call the Bark method on our Cat object.

953-001

Most type safety is enforced in C# at compile-time (static typing).

Dynamic typing is the process of enforcing type safety at run-time, rather than compile-time.  Type-checking can be delayed until run-time by using the dynamic keyword.

// Compiles ok now, but fails at run-time
dynamic c = new Cat("Fluffy");
c.Bark();

953-002

#952 – Type Safety

C# enforces type safety.  Type safety is the idea that you can only interact with an object in ways that are allowed by the object’s type.  You can’t treat an instance  of one type like it is actually an instance of another type.

Below is an example of some C++ code that is not type safe.  We use a pointer to treat a floating point value as an integer.  This results in an unexpected integer value.  This behavior is not normally something that you cannot do in C# (without marking the code as “unsafe”).

	double d1 = 1.1;

	void* ptr = &d1;    // Pointer to memory where double is stored
	int* ptr2 = (int*)ptr;   // Use the pointer as a pointer to int

	int n1 = *ptr2;     // Treat double as int

952-001

#184 – Cheating Type Safety with object Type

Since every object in C# derives from System.Object, it’s possible to “cheat” type safety by using the object type and casting objects to the desired type at run-time.

For example, assume we have a method that adds two parameters that are assumed to be numbers:

        public static double AddNums(object n1, object n2)
        {
            double d1 = Convert.ToDouble(n1);
            double d2 = Convert.ToDouble(n2);

            return d1 + d2;
        }

This is convenient because now we can pass in any numeric type we like because we can implicitly cast anything to object.

            int i1 = 5, i2 = 7;
            double d1 = 10.2, d2 = 23.2;

            // These all work as expected
            double sum = AddNums(i1, i2);
            sum = AddNums(d1, d2);
            sum = AddNums(i1, d1);

The problem is that the compiler won’t complain if we try to pass in some non-numeric object.  The following code will compile fine, but throw an exception at run-time.

            string s = "Uh-oh";
            sum = AddNums(s, 1);