Friday, April 05, 2013

Duck typing in C#

There are two types of typing, static and dynamic (also known as duck). In Static typing systems you specify the type at compile time and if your program accesses a field not declared in your type, you get a handy compiler error. By contrast in dynamic typing systems a  type is never specified, and can't be validated at compile time. Thus errors are caught as runtime exceptions.

If dynamic typing is error prone, why would you want to use it? As usual, you'd want to use it because it provides  extra power. For example, imagine you have a list of several objects that implement Quack(). How can you call  Quack on all objects that support it?
class Dog
 public string Quack() {return "Bark";}

class Cat
 public string Quack() {return "Meow";}

class Mouse

var animals = new List<object>() {new Dog(), new Cat(), new Mouse()};

If you've only used static languages, you'd think you need to add an interface IDuck{string Quack();}, and then change Dog and Cat to inherit from IDuck.  Knowing about design patterns, you might prefer to create an adapter to convert to a class that implements IDuck.  On the other hand, if you've used dynamic languages, you don't care. Instead of adding an interface, you use Duck Typing.  Duck typing gets it's name from the old adage - if it walks like a duck, and talks like a duck,  it's a duck.  C#4.0 added the duck typing feature which you can unlock via the dynamic type.  You can solve our earlier problem problem of collecting quackers like so:

var ducks = animals
// Enter the dynamic type system.
// Remove objects that can't quack
.Where(x=>x.GetType().GetMember("Quack").Length > 0 )
// return to the static type system.
.Select(x=>new {Quack = x.Quack()});

// Write the different quacks to the console.
foreach(var d in ducks) Console.WriteLine(d.Quack);

There you have it - duck typing is a powerful way to interact with your objects. Iin C# 4.0 you can mix C#'s safe static typing with the powerful, yet dangerous so use sparingly, duck typing system.

No comments: