A first look at Duck Typing in C# 4.0
I stumbled about this post over at Jon's blog called "C# 4.0: dynamic<T> ?". In it Jon wonders about the dynamic keyword and if there should be a generic version of it. That way we could be sure that the dynamic implements for example a certain interface. We all know that to be some sort of duck typing.
I got curious about it and started a little project. All I wanted to achieve is that the following would work:
- int i = 1;
- d.Test = i;
- dynamic a = d.Test;
- Console.WriteLine(a);
- // Duck!?
- IQuack t = d;
- Console.WriteLine(t.Test);
- t.Test = "2";
- Console.WriteLine(t.Test);
(where IQuack is an interface that has a Test { get; set; } signature.)
The challenge was to make Duck absolutely dynamic and certainly not aware of any IQuack interface since that would certainly be cheating. ![]()
To get a dynamic class in C# 4.0 the class has to implement System.Scripting.Actions.IDynamicObject which has one method called
- System.Scripting.Actions.MetaObject GetMetaObject(System.Linq.Expressions.Expression parameter)
At this point I encourage you to download the code sample and read along, because I will not get into every detail: blog.ducktyping source (zip)
Have you downloaded the source? Now, open the solution in Visual Studio 2010, go to Program.cs and you will notice that of course the intellisense won't work before IQuack t = d; but certainly afterwards. No biggy right?! ![]()
Implementing a dynamic class
During the next steps I will create a dynamic class that dynamically takes any Property one wishes to attach to it, and save the value for those Properties in a simple Dictionary<string,string>.
We already talked about it, that the Duck class will be our dynamic class. In order to make it dynamic we have to implement (at first) one supporting classes. Namely: MetaDuck. This class is derived from MetaObject and is returned in order to satisfy the IDynamicObject interface and to customize the behavior of our Duck.
In MetaDuck we can now override certain interesting methods. In order to make the first 5 lines of our Main method work we have to override GetMember and SetMember because we want to customize our dynamic member handling.
The trick is to pass the instantiated duck in the constructor of MetaDuck and pass it to the base class in order to enable us to work on its methods. I won't go into the details of what the expression tree is doing. Just these hints:
- Expression.Convert(Expression, LimitType) enables us to operate on the instanciated duck we passed in the constructor.
- We dynamically call the method on Duck (eg. SetMember).
Enabling that dynamic class to cast itself into strongly typed world
The main challenge now is to make our dynamic class fully capable of behaving like a strongly typed class. For that to be possible we will utilize dynamic proxies generated by Castle.DynamicProxy.ProxyGenerator. For that we need to override Convert in MetaDuck and implement the supporting IInterceptor. Basically we need to capture any member access through said proxy, and rewire it to our dynamic methods:
- public void Intercept(IInvocation invocation) {
- if (invocation.Method.Name.StartsWith("get_")) {
- invocation.ReturnValue = dynamicElement.GetMember(invocation.Method.Name.Substring(4));
- }
- else if (invocation.Method.Name.StartsWith("set_")) {
- dynamicElement.SetMember(invocation.Method.Name.Substring(4), invocation.Arguments[0]);
- }
- else {
- }
- }
Plus we have to return the proxy when a cast is requested:
- public virtual object Convert(ConvertAction action) {
- return Generator.GenerateProxy(action.ToType, this);
- }
That's it
Well, basically that's what's needed to make all of this work:
- int i = 1;
- d.Test = i;
- dynamic a = d.Test;
- Console.WriteLine(a);
- Console.WriteLine(a.GetType().FullName);
- // Duck!?
- IQuack t = d;
- Console.WriteLine(t.Test);
- t.Test = "2";
- // Would not compile anymore:
- // t.Test = i;
- Console.WriteLine(t.Test);
- try
- {
- Console.WriteLine(t.NotSet);
- Console.WriteLine("You should never see this");
- }
- catch (MemberAccessException)
- {
- Console.WriteLine("Caught expected MemberAccessException");
- }
- t.NotSet = "3";
- Console.WriteLine("Should work now: " + t.NotSet);
We can see,
- totally dynamic behavior: in line 4 the i gets excepted, even though it is not a string. We can't do that any more in line 17, when using the statically typed interface.
- Bringing a dynamic type back to the static typed world in line 11
- The dynamic type revolting when a property gets accessed that it doesn't know (yet) in line 23. (Which by the way is the behavior I _chose_ to give it. You can behave in any way you want, all you have to do is change GetMember in Duck.)
- The dynamic type "learning" a new property in line 31 even though it is strongly typed.
Even though I had a lot of fun getting this to work I can truly say that dynamic is a double edged sword that must be handled with care. But with a proper implementation of Convert this new type of dynamic behavior opens a lot of doors without killing threatening the static world too much.
Download: blog.ducktyping source (zip)

true! it reall is a double edged sword… Good work its nice to see this.
Comment on November 5, 2008 @ 10:16:34
[...] A First Look at Duck Typing in C# 4.0 (Tobias Hertkorn) [...]
Pingback on November 5, 2008 @ 15:18:03
Interesting. I’ve done some more playing with your Duck class, looking at how it behaves in scenarios like data-binding, which you might find interesting: http://marcgravell.blogspot.com/2008/11/dynamic-objects-part1.html
Comment on November 18, 2008 @ 16:23:06
Hey Marc,
thanks for the heads up. Excellent read! Cool.
Cheers,
T
Comment on November 20, 2008 @ 18:52:39
[...] to this and this blog for giving me information and [...]
Pingback on January 5, 2009 @ 23:28:56