I’ve been thinking a little this week about C# 4.0, VB 10 and the new dynamic abilities. That is, what happens when I do something like;
static void Main(string[] args)
{
dynamic o = GetSomeObject();
o.Add(101);
}
static object GetSomeObject()
{
return (new List<int>());
}
Now, if you’ve seen the sessions around this (watch this one, read this document) then you’ll know that in C# 4 this code compiles and works and that a variable declared with dynamic means that the C# compiler is prepared to get into “dynamic resolution and dispatch” for variables (parameters, return values, etc) that are declared as dynamic and that can have different meanings such as;
- If the object is a plain .NET type then the dynamic work can be done via reflection
- If the object is a COM object implementing IDispatch then the work can be done via that interface
- If the object implements IDynamicObject (a new interface in .NET 4.0) then the work can be done via that interface and this provides a plug-in point for library writers to implement dynamic dispatch over pretty much anything they like
But…we know that VB was already pretty savvy and able to do this kind of thing. For example, this is valid VB 9 code ( I think );
Sub Main()
Dim o As Object = GetSomeObject()
o.Add(101)
End Sub
Function GetSomeObject() As Object
Return (New List(Of Integer))
End Function
and so VB was already prepared to be a bit looser and do some automatic reflection (or some COM IDispatch work) so it could equally well do something like;
Sub Main()
Dim o As Object = GetSomeObject()
o.Visible = True
o.Workbooks.Add()
End Sub
Function GetSomeObject() As Object
Return (Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application")))
End Function
whereas C# couldn’t do that kind of thing without writing a bunch more code.
Now, VB 10 (watch this session, read this document) extends these “automatic reflection and IDispatch” abilities to also include the ability to call implementations of IDynamicObject so that C# 4 and VB 10 become pretty much equivalent.
However…this had me puzzling over what dynamic in C# actually means.
What does the C# compiler actually do to the type in order to say “this particular instance needs dynamic dispatch” whilst not damaging how VB (or other languages) see the same type because VB already knew how to do some of these automatic things with object instances.
It’s a pretty simple answer I think. If I take a longer winded sample as in;
static void Main(string[] args)
{
SomeProperty.Add(101);
}
static dynamic SomeProperty
{
get
{
return (GetSomeObject());
}
}
static dynamic GetSomeObject()
{
return (new List<int>());
}
then all that’s really doing is;
static void Main(string[] args)
{
SomeProperty.Add(101);
}
[property:Dynamic]
static object SomeProperty
{
get
{
return (GetSomeObject());
}
}
[return:Dynamic]
static object GetSomeObject()
{
return (new List<int>());
}
although note that the C# compiler will not let me type that code, it tells me to use the dynamic keyword. But…if I was building this in VB and then using it from C# I think I’d need to do that as in;
Public Class SomeClass
<Dynamic()>
Public ReadOnly Property SomeProperty As Object
Get
Return (GetSomeObject())
End Get
End Property
Private Function GetSomeObject() As Object
Return (New List(Of Integer))
End Function
End Class
and then I can use that from C# as in;
SomeClass sc = new SomeClass();
sc.SomeProperty.Add(101);
otherwise if I wrote the VB like this without the Dynamic attribute;
Public Class SomeClass
Public ReadOnly Property SomeProperty As Object
Get
Return (GetSomeObject())
End Get
End Property
Private Function GetSomeObject() As Object
Return (New List(Of Integer))
End Function
End Class
then my C# code wouldn’t compile unless I went and did something like;
SomeClass sc = new SomeClass();
dynamic dyn = sc.SomeProperty;
dyn.Add(101);
so I’m feeling a little more comfortable in knowing that when I used dynamic in C# it’s just sticking an attribute onto that usage to tell the compiler to apply its dynamic magic to interactions with that particular type – it’s not doing something like “creating a special kind of System.Object with some bit set on it which indicates dynamic usage”.