Thursday, April 7, 2011

Type-safety .NET

Type safety means that the compiler will validate types while compiling, and throw an error if you try to assign the wrong type to a variable.

Some simple examples:

// Fails, Trying to put an integer in a string
  
String one = 1;

// Also fails.
  
int foo = "bar";

This also applies to method arguments, since you are passing explicit types to them:
  
int AddTwoNumbers(int a, int b)
{
return a + b;
}


If I tried to call that using:
  
int Sum = AddTwoNumbers(5, "5");

The compiler would throw an error, because I am passing a string ("5"), and it is expecting an integer.

In a loosely typed language, such as javascript, I can do the following:
  
function AddTwoNumbers(a, b)
{
return a + b;
}

if I call it like this:
  
Sum = AddTwoNumbers(5, "5");

Javascript automaticly converts the 5 to a string, and returns "55". This is due to javascript using the + sign for string concatenation. To make it type-aware, you would need to do something like:
  
function AddTwoNumbers(a, b)
{
return Number(a) + Number(b);
}

Or, possibly:
  
function AddOnlyTwoNumbers(a, b)
{
if (isNaN(a) || isNaN(b))
return false;
return Number(a) + Number(b);
}

if I call it like this:
  
Sum = AddTwoNumbers(5, " dogs");

Javascript automatically converts the 5 to a string, and appends them, to return "5 dogs".

Not all dynamic languages are as forgiving as javascript (In fact a dynamic language does not implicity imply a loose typed language (see Python)), some of them will actually give you a runtime error on invalid type casting.

While its convenient, it opens you up to a lot of errors that can be easily missed, and only identified by testing the running program. Personally, I prefer to have my compiler tell me if I made that mistake.

Now, back to C#...

C# supports a language feature called [covariance](http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#C.23), this basically means that you can substitute a base type for a child type and not cause an error, for example:
  
public class Foo : Bar
{
}


Here, I created a new class (Foo) that subclasses Bar. I can now create a method:
  
void DoSomething(Bar myBar)

And call it using either a Foo, or a Bar as an argument, both will work without causing an error. This works because C# knows that any child class of Bar will implement the interface of Bar.

However, you cannot do the inverse:
  
void DoSomething(Foo myFoo)

In this situation, I cannot pass Bar to this method, because the compiler does not know that Bar implements Foo's interface. This is because a child class can (and usually will) be much different than the parent class.

No comments:

Post a Comment