One of the most interesting additions to C# 4.0, I think, is the dynamic addition. Just thinking about this makes me excited. I will jump right into a little theory, then some code.
The Theory of Dynamic
So what is this dynamic thingy? Dynamic in C# 4.0 refers to dynamic binding and dynamic binding is what happens at runtime and not at compile time. This involves binding a method, property, operator, member, etc. of an object at runtime. Yes, I know this sounds like polymorphism or like the var
keyword or even like using the ultimate base class in C# – object. First and foremost, you have to let go of what you know and remember this important fact.
dynamic != var && dynamic != object
The keyword dynamic
, casually speaking, tells the compiler that “Even though it cannot resolve the member statically, it should trust the programmer and not worry because it will/may be resolved at runtime.”
Code
Here is a sample on how you use the dynamic
keyword:
dynamic dyn = "My first time";
Console.WriteLine(dyn);
Now let’s look at some similarities and differences of var
, object
, and dynamic
for a sec.
var v = 1;
Console.WriteLine(v.GetType().ToString());
object o = 1;
Console.WriteLine(o.GetType().ToString());
dynamic d = 1;
Console.WriteLine(d.GetType().ToString());
d.Compute();
So How is this Binding Done?
Look at the following code:
class Program
{
static void Main(string[] args)
{
dynamic dyn = "hello";
Function(dyn);
Function(dyn);
Console.Read();
}
public static void Function(string s)
{
Console.WriteLine(s);
}
public static void Function(StringBuilder sb)
{
Console.WriteLine(sb.ToString());
}
}
Which version of Function
is called? The one with the string
argument.
The call to Function
above on the dynamic
type is resolved at runtime based on the runtime type information and not on the compile time’s type information. Also, the function with the most specific or closest matching parameter will be the one that is called. Pretty neat, huh? By the way, the way in which we used the dynamic
keyword above is referred to as language binding.
A Bit More Advance Stuff
So let’s say you want to develop a class that is able to calculate some basic statistics and one of your key requirements is to make it so that the calls to the methods are case insensitive. Also, you want to be able to add new functionality at will. How can you do that?
In the System.Dynamic
namespace, there is a class called DynamicObject that implements IDynamicMetaObjectProvider
. If you want your classes to have the dynamic capability, then inheriting this class gives you those capabilities. By the way, inheriting DynamicObject
or implementing IDynamicMetaObjectProvider
is called custom binding.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
namespace OliverCode.DynamicProgramming
{
public class Statistics : DynamicObject
{
private readonly double[] _arrayOfValues;
public Statistics(double[] arrVals)
{
_arrayOfValues = arrVals;
}
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args, out object result)
{
bool isSuccess = true;
switch (binder.Name.ToLower())
{
case "average":
result = _arrayOfValues.Average();
break;
case "max":
result = _arrayOfValues.Max();
break;
case "min":
result = _arrayOfValues.Min();
break;
default:
result = 0;
isSuccess = false;
break;
}
return isSuccess;
}
}
class Program
{
static void Main(string[] args)
{
dynamic stats = new Statistics(new double[]
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
Console.WriteLine(stats.max());
Console.WriteLine(stats.Max());
Console.WriteLine(stats.Mean());
Console.Read();
}
}
}
Pay attention to TryInvokeMember
method that is overridden. This means that my class can handle method calls. Actually there are a few methods that you can override:
IEnumerable<string> GetDynamicMemberNames();
DynamicMetaObject GetMetaObject(Expression parameter);
bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result);
bool TryConvert(ConvertBinder binder, out object result);
bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result);
bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
bool TryDeleteMember(DeleteMemberBinder binder);
bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result);
bool TryGetMember(GetMemberBinder binder, out object result);
bool TryInvoke(InvokeBinder binder, object[] args, out object result);
bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result);
bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value);
bool TrySetMember(SetMemberBinder binder, object value);
bool TryUnaryOperation(UnaryOperationBinder binder, out object result);
I don’t have the details on all the methods but you get the gist.
So when does dynamic not work?
As far as I know, there are 3 cases in which dynamic
doesn’t work:
- On interface members that are explicitly implemented
- With Extension methods
- Classes that subclass a base class, but hide the base classes members
So there is your introduction to dynamic programming. Happy coding and don’t forget to live.
CodeProject