- Dynamic base classes in C# 4
-
Ok, where were we? We have this new type called dynamic, and it’s used to tell the compiler to defer binding until runtime. We can construct other types with it as usual, and therefore use dynamic[], IEnumerable<dynamic>, List<dynamic>, and so on.
But last time, in answer to the entirely reasonable question, “where can I use these new types?,” I had to admit that in fact you cannot implement generic interfaces with dynamic in them.
And even that categorization is kind of dishonest. The fact is that you cannot say that you implement an interface with a dynamic in it, but in actuality you might as well imagine that you can, since you can get all the behaviors that would have been provided just by implementing the corresponding interface that has object in it.
But what about base classes?
The reason we could get away with not allowing dynamic interface implementations is because interfaces are really weird. Base classes are considerably less weird. One way in which interfaces implementations and base classes are fundamentally different is that when you have an interface implementation, you get a conversion to that interface. However, when you derive from a base class, you get more than a conversion, you get pretty much everything. Take a look at the following classes:
class Base<T>
{
T M() { return default(T); }
}
class DerivedO : Base<object>
{
}
class DerivedD : Base<dynamic>
{
}
Now, let's look at this:
var o = new DerivedO().M();
var d = new DerivedD().M();
Ok, what should the types of o and d be? Clearly, o needs to be object, and d needs to be dynamic. And I am happy to say that they are, and that you can do this. Can you see how, even if the method M were defined on a base interface, that would have been entirely irrelevant for the purpose of this example, and the return type would have been determined based on the actual method implementation in whichever class defined it?
So dynamic in base classes works.
It’s nice for the compiler implementation that you can only have a single base class, since that means that we can easily mark the class in a single location that its base class is defined this way. In my last post, I mentioned the way this would have been a problem with the dynamic interface implementation implementation—there are too many of them.
I should point out another detail. Try this:
class C : dynamic
{
}
You can’t do it. Because what on earth would that mean? Would “this” be type dynamic or type C? “base” would be dynamic, right? Why would you want to do that to yourself? Thankfully:
error CS1965: 'C': cannot derive from the dynamic type
More questions
Ok, we can have dynamic in the base classes, but not “naked dynamic,” and we can’t in the specification of interface implementations. How about
class C<T, U> : where T : dynamic, U: List<dynamic> { }
... is that legal? What do you want it to mean? Next time.
Additional stuff
I’ve delayed too long in setting up a reasonable source code formatter here, but I’ve finally installed SyntaxHighlighter. Thanks to Alexandre for putting together such a convenient tool.
I’ve also abandoned the notion of numbering my posts on C# dynamic. It makes more sense to have descriptive titles, especially since I have a lot more to say.
- C# “dynamic,” Part VII
-
It has been a while since I posted anything here, and I have the same excuse everyone else does. Work, holidays, and generally being pretty busy. But enough of that, it’s February (!!!) and that means we’re getting closer to shipping C# 4.0 and dynamic and making all of this a much less abstract exercise for everyone who wants to see it and use it.
But let’s answer the question I left off with last time.
Implementing dynamic interfaces
So, I asked last time, can you implement IEnumerable<dynamic>?
Well, to begin with, we established last time that IEnumerable<dynamic> is a real type. It exists! It derives from IEnumerable, and it has an extra method called GetEnumerator that returns an IEnumerator<dynamic>, just like any other constructed generic type would have. It’s different from IEnumerable<object>, although there is a “structural conversion” between the two that I mentioned last time.
But the question is, can you implement it? In other words, what happens when I try to compile the following, and if successful, what does it do?
public class C : IEnumerable<dynamic>
{
public IEnumerator<dynamic> GetEnumerator()
{
return null;
}
...
}
Before we answer that directly, let’s talk about what it means when you say that, in C#.
The first thing implementing an interface means is: The compiler will verify that you have implemented, in class C, all of the methods that are defined in your interface, and it will make sure that they are virtual and marked as overriding the interface methods, if necessary.
In this example, GetEnumerator does in fact qualify as the implementation of the interface method GetEnumerator (one of them, anyway—IEnumerable is confusing). But you know what? So would have this method if I had returned IEnumerable<object>. It’s not because there is a conversion between the two (though there is, and it’s the structural one I mentioned in part VI), but it’s because when we look at method overrides and overloads, we treat object and dynamic as the same!
Have I mentioned that bit before? It’s a little weird, but if you think about it for a moment, it’s clear why. When we emit metadata, dynamic is going to come out as object anyway. So, what if you tried to define a class like this:
public class C
{
public void M(object x) { }
public void M(dynamic x) { }
}
Well... We could never emit that, because the M’s would collide, so the language can’t allow overloads that differ only in dynamic/object. Similarly, if you try to override a method and it differs only in dynamic/object, that’s ok! In other words, in the interface example, that GetEnumerator would have to work regardless of whether it returned IEnumerator<dynamic> or IEnumerator<object>. And also, either of those two methods would have worked if the interface being implemented was IEnumerable<dynamic> or IEnumerable<object>.
Let’s leave that alone for the moment, though, and talk about...
The second thing implementing an interface means: You get a new implicit conversion from your type to the interface. This is clear, right? If I implement IEnumerable<dynamic>, I should now be able to say such things as
IEnumerable<dynamic> ie = new C();
Those are the two big things that I would achieve, were I able to implement IEnumerable<dynamic>. And now let me answer the original question: No. You cannot implement an interface that includes dynamic.
Why?
Well, for one thing, it doesn’t actually give you anything that you didn’t already have. The first thing and the second thing are already there if you implemented IEnumerable<object>. In that case, you still would have been able to define GetEnumerator the way we did, and you still can convert C to IEnumerable<dynamic> (again, because of the structural conversions). Think of it this way: if anyone ever looks directly at your type C, they are never going to “see” what interfaces you implement. They only “see” them when they cast, and at that point, your IEnumerable<dynamic> didn’t do them any good.
That’s a fine reason, but you might respond, why not let me do this anyway? Why impose this limitation that seems artificial? Good question. I encountered this for the first time when I was trying to get the compiler to emit these things, and I realized very quickly that there was no where for me to emit the [Dynamic] attribute that we use to mark dynamic types. The metadata team reported that a reading of the CLI spec seemed to indicate that the tables for interface implementations and custom attributes might have permitted it, but anyway no one we know of has ever done this, and it would have been effort expended. We have priorities and a limited budget of time, and this didn’t make the cut.
An alternative suggestion might be to allow you to say IEnumerable<dynamic> but really emit IEnumerable<object>, because, after all, they are the same in this context anyway. This option was rejected mostly because it’s confusing to users and the tools. Round-tripping would break, so that if you looked at your type in the project or solution that defines it, it would appear to be one thing, and if you looked at it from the perspective of a project that merely references it, it would be something else. Not good.
So you can’t do this. The error is something like:
error CSXXXX: 'C': cannot implement a dynamic interface 'System.Collections.Generic.IEnumerable'
There’s more! I haven’t even talked about implementing Base<dynamic>. Next time!
Previous posts in this series: Part VI, Part V, Part IV, Part III, Part II, Part I
- C# "dynamic," Part VI
-
We left off last time with this piece of code
public class C
{
public static void M(int i) { }
public static void M(string s) { }
}
...
dynamic d = GetSomeD();
C.M(d);
...together with some question about what the compiler could possibly do on the last line, when M is called. The answer is, of course, the compiler can't do much. If it knew what type was really behind d, then it could insert an assignment conversion and call the correct M. But the point of "dynamic" is that the compiler has no idea whatsoever what type is back there. The best it can do is defer its work until it does know what types are there--wait until runtime!
Overload resolution deferred
Overload resolution in C# is a bit complicated. I tend to think of C# method calls as more or less just depending on the target object and the name. But that's the naive view; since the language allows overloading methods on their names, we actually get into quite a mess trying to figure out which one to call. By the time you throw in generic methods with type inference, extension methods, params arrays, and now named and optional parameters, there's actually quite a bit in the language specification that says how you're supposed to sort all this out.
And since we can't decide which M to call in the example above, it just got more complicated. How do we know when to defer until runtime?
First, we don't defer if we don't need to. If dynamic is not involved at all, then of course we do what we've always done and nothing changes. Another case where we don't need to do anything is if dynamic is involved, but the old overload resolution rules give you an answer. This can happen, for instance, if you have dynamic as a formal parameter of one of the overloads, such as:
public class C
{
public static void M(int i) { }
public static void M(dynamic d) { }
}
...
dynamic d = GetSomeD();
C.M(d);
In this case, the compiler will resolve to the second M, since the conversions work out. The trick is that there is an implicit conversion from dynamic to itself.
If none of the overloads that we look at actually work, then we need to try something else. It goes like this: while you are looking for methods to test, if ever you see one that fails only because there was a dynamic argument in one position and no conversion, then just "pretend" that there exists a method that takes dynamic everywhere and returns dynamic. So in this case, the pretend method would look like:
public static dynamic M(dynamic d) { } // not real
But be careful--don't add the pretend method if there is already an existing real method that matches its signature (as in the second example). Also, ref and out parameters are a little special, so if you see them you need to alter the shape of your pretend method a little, but that's not too interesting.
So then what? Well, at the end of overload resolution, when you have all your candidate methods in hand, you compare them to see which is better as usual (this is another complicated part of the spec that involves testing arity and conversions and such), and if it turns out that you pick the "pretend" method, then that means you need to defer overload resolution until runtime.
And the way the compiler indicates this deferral is it makes a CallSite to ask the runtime binder to do its thing, almost as if you had called any old method on a dynamic target. The target is not dynamic, though, if there even is one! For instance, notice that in the examples above, the methods are static. So what we've done is produced a dynamic call site for a static method. I think that's weird, but there's a few legit examples that come up all the time, such as Math.Sign, or Math.Abs that each have a variety of overloads for different numeric types.
Incidentally, while we were designing this feature, we called the pretend method "the phantom method." I am not sure if that name will stick in the spec.
Some more conversions
So the deferred overload resolution as well as the assignment conversions are two different strategies that arose in an effort to get "dynamic" to work just as you expect it. But there are some other changes that make the dynamic type a little weird.
A couple posts ago, I talked about how dynamic doesn't really exist in the framework, that it's just a compiler construct (although from the perspective of the compiler it is a real type). Well, if that's the case, then whenever I have, say, a List<dynamic>, I should be able to store it in a space reserved for a List<object>, and vice-versa, right?
List<dynamic> ld = GetAList();
List<object> lo = ld;
Of course I should! How do I do that? Well, we added more conversions. First, I need to define a mapping of types. For a given T, let red(T) ("T reduced") be the type T except with all the occurrences of dynamic replaced by object. So red(Dictionary<dynamic, object>) == Dictionary<object,object>. We added the following conversions.
- If there is an implicit reference conversion from red(S) to red(T), then there is also an implicit reference conversion from S to T, except in the case where S is dynamic and T is object.
- If there is an implicit reference conversion from S to T and from T to U, and one of them is a conversion added by rule 1, then there is an implicit conversion from S to U.
- If there is an explicit reference conversion from red(S) to red(T), then there is also an explicit reference conversion from S to T.
I call these conversions "structural conversions," since they exist only because they preserve the runtime structure of the objects being converted. This is probably not the language that you will see in the final C# 4 specification since this area is not 100% baked yet.
There's more weirdness for next time, too! Can you implement IEnumerable<dynamic> or derive from Base<dynamic>? Should you be able to? What does each of those things mean?
Previous posts in this series: Part V, Part IV, Part III, Part II, Part I
- C# "dynamic," Part V
-
Let's look at this:
dynamic d = null;
object o = d; // not an implicit conversion
Last time, I said that the conversion on the second line is not an implicit conversion. If you know C# already, that sounds preposterous. Just look at it; of course it's an implicit conversion! It's not though. It's called an "assignment conversion."
Assignment Conversions
Assignment conversions are a new third kind of conversion, between explicit and implicit conversions. Every assignment conversion is also an explicit conversion, and every implicit conversion is also an assignment conversion.

Why would we have introduced such a thing? Let's talk about the path that got us here. Initially, we considered having implicit conversions from dynamic to everything. That way you could always assign a dynamic value to any variable, or pass it to any method, and it would just work out. That's good. We want that. Why? Well, dynamic lets you work without type information, which means you that you don't need to insert casts everywhere, and if we required casts just to get back to the typed world (i.e., assign back to some typed local), we wouldn't have saved you too much typing or made your code look very much better.
There are better reasons not to have implicit casts from dynamic to everything, though. Recall that we do have implicit conversions from everything to dynamic. Maybe you can see what would have gone wrong with this scheme: imagine that we also wanted these simple implicit conversions to be transitive, and all the sudden there would have been implicit conversions from any type to any other type, "through" dynamic. It would be mayhem.
And even without transitivity, we'd face a problem. If dynamic were implicitly convertible to any type, then what happens during overload resolution?
public class C
{
public static void M(int i) { }
public static void M(string s) { }
}
...
dynamic d = GetSomeD();
C.M(d);
When calling M on the last line, or any time you are converting a dynamic to some parameter type, what should you do? If there is an implicit conversion from dynamic to int and also an implicit conversion from dynamic to string, then what we have here is an ambiguity error at compile time. Even if there were some cases where we could say that one is better than the other (perhaps dynamic to object is better than dynamic to int), there are plenty of cases where we clearly couldn't. And if all these cases are ambiguities, then again, we've forced you to write a conversion to effectively pick one of these overloads by hand, which is not cool.
So what is an assignment conversion then?
- There is an assignment reference conversion from dynamic to any other reference type.
- There is an assignment unboxing conversion from dynamic to any value type.
As a matter of fact, these are exactly the explicit conversions I mentioned from dynamic last time. So forget that I said they were explicit conversions. They're actually assignment conversions! And in fact, these conversions together with the implicit conversions are all of the assignment conversions.
When?
We've seen that assignment is one place where the compiler will insert an assignment conversion:
dynamic d = GetSomeD();
Worksheet ws = d; // assignment conversion
But that's not all! The C# 4 spec changes in such a way that quite a few "assignment-like things" now utilize assignment conversions. Returns, and yield returns do:
return d; // assign. conversion to return type
yield return d; // assign. conversion to iterator type
Property and indexers:
foo.Prop = d; // assign. conversion to Prop's type
foo[1] = d; // assign. conversion to indexer's type
And a few other less frequent cases, like array initializers (among some that I am surely forgetting right now):
bool[] ba = new bool[] { true, d }; // assign. conversion
There are also some kind of one-off special cases where a statement form uses an assignment conversion, such as foreach
foreach (var x in d) {} // assign. conversion to IEnumerable
or
using (d) {} // assign. conversion to IDisposable
Wait, what about overload resolution?
One of constructs that does not use assignment conversions is overload resolution, for the reason cited above. If arguments to method calls were to be converted using assignment conversions, then we'd be in the mess where pretty much every time you passed a dynamic to some method you'd have an ambiguity.
However, now it would seem that we have the opposite problem. This snippet:
public class C
{
public static void M(int i) { }
public static void M(string s) { }
}
...
dynamic d = GetSomeD();
C.M(d);
won't compile for entirely different reasons! There's no conversion from d, the argument in the final call, to any type that is an actual parameter on an M in C. Obviously, we need this to compile. You can see, in the CTP, that it does. In order to accomplish that, we changed the rules for overload resolution.
Before I tell you how those rules changed (next time), try a little thought experiment: what is everything we know about M at the call site in the last line, and what are the different strategies for emitting code that calls one of the overloads? What does the programmer expect?
And one last thing. This compiles in the CTP:
List<object> lo = GetAList();
List<dynamic> ld = lo;
What kind of conversion is that? I'll give you a hint. It's not covariant.
Previous posts in this series: Part IV, Part III, Part II, Part I
- C# "dynamic," Part IV
-
Today, let's geek out about the language design regarding the dynamic type.
Type in the language vs. Type in the runtime
One thing that lots of people already know is that when you say "dynamic" in code, you can think of it as "System.Object" in your assembly, because that's how the compiler emits it.
dynamic d = 2008; // A lot like "object d = 2008;"
List<dynamic> x = new List<dynamic>(); // ...like "List<object>"
There is no "System.Dynamic" type. However, despite that there is no runtime type that corresponds to the thing you just typed, dynamic is an honest-to-goodness type as far as the language is concerned, although it behaves a little weirdly.
Note that this is different from "var." When you say "var" in C# source code in place of a real type, the compiler infers the type and declares the local variable with the appropriate type, which could be anything. It's a shorthand for local variable definitions. You cannot have List<var>s or var[] expressions. You cannot derive from something with a var in it, or have a var field. Var is a feature that makes local variable declaration statements better. Dynamic is not.
How do you think of types?
There are lots of relationships between types in C#, and the most important two that I can think of are the inheritance relationships and the convertibility relationships. And it is in those relationships where dynamic starts to diverge from the way you're used to thinking of types. I'm about to leave out a lot of detail and edge cases, so bear with me.
I think of the inheritance relationship like this: There is a big inheritance tree, and its root is System.Object. Pretty much all types live there, except for interface types. Interface types have their own inheritance relationships that form a lattice with no root. And furthermore, the tree of non-interface types is bound to the lattice of interface types in various locations whenever a type implements an interface. You can build families of types by parameterizing them (generics) but that doesn't screw up this model so just forget about it for now.
That's kind of abstract. Here's a picture. The blue diagram shows you the "real" object types, and the green diagram shows you the interfaces. Most things live in the blue diagram. Objects, arrays, delegates, enums, numeric types, all that.
The things at the heads of arrows are the base types, and at the tail they're the subtypes. I haven't drawn the arrows from blue things to green things.
Ok, what about convertibility (sometimes, "compatibility")? Well, convertibility is a separate relationship that is informed by the picture above, but it is not the same thing. I don't think of convertibility as a picture at all. I think of it as a list of rules. And actually, there are two kinds of conversions: explicit and implicit. All implicit conversions are also explicit conversions.
How do those rules look? Well, here's one of them: There exists an implicit conversion from S to T if T is a base type of S. In other words, the arrows above are also implicit conversions.
Base myBase = myDerived;
Here's another: There exists an explicit conversion from T to S it T is a base type of S.
Derived myDerived = (Base)myBase;
And another: There is an implicit conversion from int to double.
double myDouble = myInt;
And: There is an implicit conversion from S to T if the user defined a special static implicit conversion method in the definition of S or T.
string s = myThingWithUserDefinedConversionToString;
There are lots of these rules, and some of them are given special names because they have certain characteristics, such as "boxing," "numeric," "reference," "user-defined," etc. I said I don't think of these as a picture because if I had to draw a picture like the above, there would simply be too many arrows for it to be helpful.
The difference between the explicit conversion and implicit conversions at compile time is that you must specify a cast to invoke an explicit conversion. The difference at runtime is that an explicit conversion may fail, but an implicit conversions should not. This last distinguishing characteristic sounds like something that's going to have to be relaxed a bit for dynamic.
What about dynamic?
So none of this so far is new. But here's the question: if dynamic is really a type, then where does it sit in the above inheritance picture, and what rules got added to the (long) list of conversion rules?
It's a good question. Let's answer the first part with a picture:
That was easy. The type dynamic stands alone. It does not derive from anything, even object. It is a unique, isolated, stand-alone weirdo. And you cannot introduce types that derive from it, either. In that sense, it's not very much like object at all!
The conversions are, though. There is an implicit conversion from just about everything to object, and they are more than just the "implicit reference conversions" that come right out of the arrows in the hierarchy tree. There are also conversions from interfaces to object, and value types to object, and the degenerate identity conversion from object to object. We "copy" all of these conversions to the dynamic world:
- There is an implicit identity conversion from dynamic to dynamic.
- There is an implicit reference conversion from any other reference type to dynamic.
- There is an implicit boxing conversion from any value type to dynamic.
Great! So we got back all those conversions that we "lost" due to the fact that dynamic sits outside of the usual inheritance picture. What about explicit conversions?
- There is an explicit reference conversion from dynamic to any other reference type.
- There is an explicit unboxing conversion from dynamic to any value type.
Wow! That's everything, right? We more or less get dynamic to behave just like object with respect to its conversions by adding these new rules. Maybe that's what Anders means when he says that dynamic can be though of as a peer to object. Did we screw up anything? What's happening here that's unexpected? Well, This all seems pretty straight-forward, but it doesn't get us everything we want.
The first weird thing: there is no implicit conversion from dynamic to object. Why not? Well, there are no implicit conversions mentioned above from dynamic to anything! Except the identity conversion of course. Why did we do that? Well, it'll come out in the wash as I explain more, but the short story is that if there were implicit conversions from object to dynamic and back again, it would be very hard to distinguish them from one another when we perform operations that expect one or the other. So we cut the chain.
But wait a minute, in the CTP, you can type this:
dynamic d = null;
object o = d;
And it compiles. That's because it's not an implicit conversion!
More next time: what kind of conversion is that? What other new crazy conversions have we had to add? What about signature matching, and constraints? How does overload resolution work?
Previous posts in this series: Part III, Part II, Part I
- Channel 9 Video on C# 4
-
I'm a little backlogged at work right now, and I'll get back to some dynamic posts as soon as I can. In the meantime, Eric, Sam, Mads, and I talked with Channel 9 last week, and the video has just been posted. I look forward to watching it myself! Here's hoping I haven't said anything too embarrassing.
Channel 9 "Inside C# 4.0"
- C# "dynamic," Part III
-
Here are a few good resources that you ought to look at for information about dynamic from PDC:
Anders Hejlsberg's talk, "The Future of C#" - Among other things, this talk is a great introduction to dynamic. I recommend it highly! There are some good demos, and Anders' presentation is very compelling. I especially like the parts where people applaud.
Jim Hugunin's talk, "Deep Dive: Dynamic Languages in Microsoft .NET" - Jim is the DLR's architect. There are some details about implementing your own dynamic objects, which I touched on only superficially yesterday. He also talks about the way that C# (or any language) generates dynamic call sites and what they do at runtime.
Mads Torgerson's white paper, "New features in C# 4.0" - Some more information, this time written by the language PM. Mads is the guy who'll ultimately write and edit the updated language spec, which doesn't yet exist.
If you watch these presentations, and you start to play around with the PDC 2008 CTP, you may notice something strange. A few things just won't work. For instance, when you try to get an indexer on a dynamic (d[0]) or perform a binary operation with a dynamic ("Hello from C# " + d), the compiler is going to tell you you can't do that. And in Jim's talk, he implements IDynamicObject with a great helper class called DynamicObject where you only need to override some virtual methods. But the PDC bits don't have that type.
It may be obvious, but the thing that's going on here is that the CTP build for PDC was snapped sometime in the summer, and some of the presenters are using a newer, more complete build. We've done a lot of work since the CTP was snapped, and I regret that you can't see it all first hand right now, but I hope you'll understand that this is the nature of a CTP. I'll try to be clear when I post about what will work for you, and what won't.
For instance, Part II in this series (the implementation of IDynamicObject) will work for you! I don't think Part I will, though (it uses indexers).
If you're wondering what does work for dynamic C# in the CTP build, here's the short story: (a) dynamic method calls, (b) dynamic property gets/sets, and (c) dynamic conversion sites.
Previous posts in this series: C# "dynamic"; C# "dynamic," Part II
- C# "dynamic," Part II
-
Yesterday, I made an attempt to introduce the C# dynamic feature by describing what change there has been to the language, what scenarios we hope to affect by that change, and some overview of what dynamic operations look like in C# 4 as it stands in the preview distributed at PDC 2008.
One thing that I did not mention was this: that the language changes are entirely focused around consumption of dynamic types, not definition of those types. This is not to say that you cannot define dynamic types--just that the C# language has not change in any way so as to provide you a shortcut. We have not added a "method_missing," nor are any of the regular types you define in C# capable of somehow dynamically acquiring properties. And you can't say something like "dynamic class C" to define such a class.
If you want to define a new type that accepts dynamic operations, then it's easy to do so, and you don't even need C# 4. You just implement IDynamicObject, which is the interface that tells the DLR, "I know how to dispatch operations on myself." It's a simple interface, in the spirit of IQueryable, with a single method that returns a "MetaObject" to do the real heavy lifting.
I want to make clear at this point that I am about to provide an example of how to use the DLR, but that I am only doing so in order to demonstrate how these objects play with the C# 4 language features. There are other blogs that are certainly better sources for information about the DLR.
So, here's an implementation:
public class MyDynamicObject : IDynamicObject
{
public MetaObject GetMetaObject(Expression parameter)
{
return new MyMetaObject(parameter);
}
}
Simple enough! Here's the MyMetaObject definition. The MetaObject "knows how" to respond to a variety of actions including method calls, property sets/gets, etc. I'll just handle those (no best practices here; this is a minimal implementation):
public class MyMetaObject : MetaObject
{
public MyMetaObject(Expression parameter)
: base(parameter, Restrictions.Empty)
{
}
public override MetaObject Call(CallAction action, MetaObject[] args)
{
Console.WriteLine("Call of method {0}", action.Name);
return this;
}
public override MetaObject SetMember(SetMemberAction action, MetaObject[] args)
{
Console.WriteLine("SetMember of property {0}", action.Name);
return this;
}
public override MetaObject GetMember(GetMemberAction action, MetaObject[] args)
{
Console.WriteLine("GetMember of property {0}", action.Name);
return this;
}
}
This is exactly what, say, IronPython might do to implement the dictionary lookup that it needs to do for its members. And when I say "exactly," I mean "sort of" because of course IronPython's implementation is considerably more complex and robust. But this gets the job done. Suppose I want to now use C# to invoke these things using the new syntax. That's the easy part! Check this out:
public class Program
{
static void Main(string[] args)
{
dynamic d = new MyDynamicObject();
d.P3 = d.M1(d.P1, d.M2(d.P2));
}
}
So I take my MyDynamicObject that I defined above, and then I get a few properties, call a few methods, and set a property for good measure. If you compile this, you get the following output:
GetMember of property P1
GetMember of property P2
Call of method M2
Call of method M1
SetMember of property P3
I think that's pretty cool.
Next time I'll talk more about the dynamic type again, in the C# language, and how it behaves. I just wanted to take a little diversion to clear up the fact that we've really done a lot of cool work on the consumption side, and your code ought to look better for it when you're consuming these things. If you're defining them, then you're in DLR-land, and you might even be writing in python or ruby or some other language. I'll provide pointers to those issues as I get them.
Previous posts in this series: C# "dynamic"
- C# "dynamic"
-
PDC 2008 arrives today, and that means that I am finally able to talk publicly about some of the things I've been working on for the next version of C#. What a relief! I am excited for the world to see some of this stuff, and to start receiving more customer feedback about it.
This afternoon, Anders Hejlsberg presented a talk called "The Future of C#" that I confess I have not seen a dry-run of. I'm sure it went fabulously, though. In that talk, he introduced the "dynamic" feature in C# 4. The short story is that we plan to allow users to perform operations, the details of which are not known until runtime, using the dispatch mechanism supported by the DLR (Jim Hugunin is giving another talk today called "Deep Dive: Dynamic Languages in Microsoft .NET").
Charlie Calvert and Mads Torgersen let slip a few months ago that this was coming, and at the time we got a lot of feedback about the particulars of that proposal (which you might like to go back and look at, but keep in mind that it is out-dated). In fact, we've been through a number of designs, and we've implemented a prototype and a few false starts before we settled on what we believe is the best design: dynamic is a type.
The type "dynamic"
So here's an example of what you might see in C# 4, the result of which is a runtime/late-bound dispatch to the method "Foo" on some local variable:
dynamic d = GetADynamicThing();
d.Foo();
As you can see, the local variable "d" is of type dynamic, which is a proper type supported by the compiler, and which you can mention in most places that you can mention a type. This code compiles, and it would have compiled no matter what method name you had used. In that sense, "dynamic" is a very special type. It appears to support almost any method name, any property or field, in fact, most anything that you could do with some variable, you can do with a dynamic variable.
The difference of course is that instead of emitting an IL call to something called Foo, which the compiler clearly cannot do since there is no type involved that defines anything called Foo, the compiler emits a "dynamic call site" that manages that operation at runtime, using the C# Runtime binder in conjunction with the DLR, both of which are library components. More details on this later.
This allows you to use the C# language, with the brevity and syntax you've become accustomed to, to invoke methods on python or ruby objects, or on any COM IDispatch object, even without an interop assembly, or on any other object that "knows how to dispatch itself" (you could imagine, say, a DOM that uses this to expose its content as properties). And you can do this on regular old .NET objects too.
And since dynamic is a type, you can use it in more that just locals. For example, this compiles:
class C
{
public dynamic myField;
public dynamic MyProp { get; set; }
public dynamic MyMethod(dynamic d)
{
return d.Foo();
}
public delegate dynamic MyDelegate(dynamic d);
}
If you were to get the value of MyProp from some instance of C, and then do anything to it (maybe you could call the method Foo?), then that would be a dynamic dispatch.
A little behind-the-scenes
There is a lot going on here that I am omitting, the details of which I plan to bore/fascinate you with over the course of the next few weeks. Let me at least show you what one of these things looks like if we crack open the assembly. Assume the following class definition:
class C
{
public dynamic MyMethod(dynamic d)
{
return d.Foo();
}
}
That's one method that includes some dynamic params as well as a single "dynamic call site" to call the method Foo. Reflector tells you that the assembly actually looks something like this (simplified a bit):
class C
{
[return: Dynamic]
public object MyMethod([Dynamic] object d)
{
if (MyMethodo__SiteContainer0.p__Site1 == null)
{
MyMethodo__SiteContainer0.p__Site1 =
CallSite<Func<CallSite, object, object>>
.Create(new CSharpCallPayload(
CSharpCallFlags.None, "Foo", typeof(object), null,
new CSharpArgumentInfo[] {
new CSharpArgumentInfo(CSharpArgumentInfoFlags.None,
null) }));
}
return MyMethodo__SiteContainer0.p__Site1
.Target(MyMethodo__SiteContainer0.p__Site1, d);
}
[CompilerGenerated]
private static class MyMethodo__SiteContainer0
{
public static CallSite<Func<CallSite, object, object>> p__Site1;
}
}
As you can see, the publicly visible members that use the type dynamic actually, behind the scenes, use the type object when they are emitted. There is no framework type "dynamic." However, those "objects" are all decorated in such a way that the compiler (or anyone else) can tell that they are meant to be handled dynamically.
There is also a static field to hold one of the DLR's dynamic call sites for each dynamic operation that you perform. In this case, there is just one, and it corresponds to the method call to Foo. It is initialized inline with the code that uses it in a lazy manner, and invoked with the "Target" field which is actually a delegate that does the right work.
I admit that code looks scary! But the important thing is that it's something that you don't have to write. The compiler does it all for you. Again, lots of detail is being left out here--for instance, what really happens at runtime, the perf characteristics, and lots of juicy language considerations--but we'll get to all that later.
A scenario we made better by all this
I want to end this post by responding to something that Scott Hanselman posted a little while ago, about the pain of programming against COM in C#. Go look at this post:
http://www.hanselman.com/blog/BackToBasicsVarDim.aspx
...and consider the 53-line horror of what you need to write to talk to Word via its COM object model. In C# anyway. Especially the last half, where there are a few calls to "InvokeMember." Well, one of the benefits we get from the dynamic feature is that all this InvokeMember nonsense is no longer required. Check out the same 53 lines in C# 4 (now considerably smaller):
ApplicationClass WordApp = new ApplicationClass();
WordApp.Visible = true;
string fileName = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\NewTest.doc");
Document aDoc = WordApp.Documents.Open(
fileName, ReadOnly: false, Visible: true);
aDoc.Activate();
string propertyValue =
aDoc.CustomDocumentProperties["CustomProperty1"].Value;
aDoc.CustomDocumentProperties["CustomProperty1"] = "Hanselman";
foreach (Range r in aDoc.StoryRanges)
{
r.Fields.Update();
}
If you look closely, you'll notice that we don't even mention the dynamic keyword in this code snippet. It comes in anyway, though, given that we import COM interop interfaces specially so that you automatically get dynamic calls where appropriate.
If you look closely again, you'll see that there's more here than just dynamic. How about that syntax on the Open() call? More on that later.
Like I said above several times, there's a lot about this that I've left unsaid, and in fact there are a few bits that are even yet-undesigned. I'll follow up with more information soon. If you have feedback or questions, please let me know! And happy PDCing if you're in LA this week.
PS, I feel obliged to tell you that this post describes a product that has not shipped and is not yet complete. I cannot make any claim to know exactly what C# 4 will look like when it does ship. The code here corresponds roughly to what you can do with the PDC 2008 release of Visual Studio 2010 CTP. This posting is provided "AS IS" with no warranties, and confers no rights.
- Events in Space
-
My last post was many months ago, and I've been pretty busy here since then. Nobody who starts a blog means to neglect it, even though mostly that's what happens. I won't let it go for so long again. =)
Anyway, we were talking about events. Field-like events in particular, and the nastiness of their implementation with respect to the way they use synchronization. Sam, also on my team, has a post that has to do with field-like events, in particular that when you declare them virtual and then override them, you should be a bit careful.
I want to bring up something else about events, which is their performance in space--how much of it they use. On a per-instance basis, each field-like event you declare takes up at least the size of a delegate field. Is that the best you can do?
WinForms doesn't think so. Take a minute and reflect over System.Windows.Forms.Control and look at the events. There are 68 of them. I won't list them all here, but they're things like "Click," "GotFocus," "KeyDown," etc. Now, Control is the fundamental base class for pieces of WinForms UI, and so there are likely to be a lot of instances around. If these events were all field-like, then every piece of UI would be bloated by 68 delegate fields. That'll add up quickly, but the important bit is that it's almost all a waste. It's not the case that control events are frequently subscribed to. Mostly they're not. You create a button and then you listen for Click and maybe one or two others, but you're not adding 68 events on the thing.
So what did they do? Well, you can look at the events. They implemented their own accessors, and those accessors, instead of dealing in terms of delegate fields, deal with a list of delegates that have been used so far in that instance.
This strategy allows the list to be sparse.
See, if no one ever calls add for a particular event, then it never gets a list entry. If someone does, then it has a list entry and the total footprint grows by that amount for your instance, but that's ok. You're paying for what you're using!
This is a really good idea, if you're in the same boat. Of course... you're probably not. Just having a handful of events won't warrant this amount of attention, since the container is going to have overhead. And if you implement a lot of events but they're always used, or if you don't have a lot of instances, you probably also don't want to do this. Oh, and if you're going to try an optimization like this, test it to see if it gets you anything. You don't want to wind up with an implementation that's worse than you started with (which is actually not that unlikely--an obvious implementation here uses a Dictionary, but Dictionaries have quite a lot of overhead). You can see that the particular implementation used by System.Windows.Forms.Control has a tiny, hand-crafted list.
So that's another reason sometimes not to use field-like events.
- Field-like Events Considered Harmful
-
Hi all, my name's Chris Burrows, and I'm a developer on the C# Compiler team here in Redmond. I'll introduce myself further in a subsequent post, but I just want to start off with a note that has at least a little substance.
So let's talk about C# events as they've existed for a long time now, and their implementation in the compiler. Last week, I was responding to an issue involving events, I was surprised to discover that the language spec tries to make some guarantee that field-like events are, as it says, "thread safe." When I say "field-like events," I mean events for which you have not defined your own add and remove accessors. Let's have a look at the C# 3.0 specification (10.8.1):
In order to be thread-safe, the addition or removal operations are done while holding the lock (8.12) on the containing object for an instance event, or the type object (7.5.10.6) for a static event.
Thus, an instance event declaration of the form:
class X
{
public event D Ev;
}
could be compiled to something equivalent to:
class X
{
private D __Ev; // field to hold the delegate
public event D Ev
{
add
{
lock (this) { __Ev = __Ev + value; }
}
remove
{
lock (this) { __Ev = __Ev - value; }
}
}
}
Ok. Let's start at the beginning. You should be wary of the language here that implies that the implementation of events is "thread safe." Thread safety, if you care about it at all for this event, is still something that you need to worry about on your own. What happens if you have some other method in the class that adds or removes delegates from the event field? Are those in a context where you've gotten a lock on the proper object? How about the invocations of that delegate? And what if thread safety isn't even a concern for you in this case? If so, it's a little weird that you have to pay for it.
There are bigger concerns though--in a sense I suppose it's kind of obvious that if you want thread safety you're going to have to worry about it in the rest of your code. But look at the lock. It uses the containing object's sync block! You're never supposed to lock(this)! It's one of those things on .NET style lists marked "never do." The big issue here is that the containing object's sync block is essentially public. If anyone else happens to use it elsewhere (for instance, your class's consumers), then you've set yourself up for threading problems.
And it gets worse. If you read on in the spec, you'll see that if we had declared that event static, then the lock would not have been on this, because there is no this. It would have been on X's type:
class X
{
private static D __Ev; // field to hold the delegate
public static event D Ev
{
add
{
lock (typeof(X)) { __Ev = __Ev + value; }
}
remove
{
lock (typeof(X)) { __Ev = __Ev - value; }
}
}
}
This has the potential to be a huge problem! It's got all the issues associated with lock(this), except that the type object can be loaded in a domain-neutral context, so that it's shared across all app domains. There, now you've just busted through the app domain isolation and you can cause issues across your entire process for anyone using this event. Potentially.
But let's back up a second. The language in the spec is a little weasely. It says that these forms "could be compiled to something equivalent to..." What does that mean? In fact, in the most up-to-date C# compiler (as well as previous versions), the code is compiled to something equivalent to these add/remove blocks, but only in the case where X is a reference type. If we look at the IL for X.Ev.add, it does not contain the lock or any mention of the Monitor class, but the method's metadata looks like this:
.method public hidebysig specialname instance void
add_Ev(class D 'value') cil managed synchronized
{ ... }
See that "synchronized?" That tells the runtime to wrap the method in the equivalent of the two lock statements that the spec mentions (depending on whether the method is instance or static). If you want to accomplish the same thing explicitly (which maybe you don't), you would get System.Runtime.CompilerServices in scope and decorate the method with:
[MethodImpl(MethodImplOptions.Synchronized)]
The compiler only inserts this for events on reference types because if you've defined the same event on a value type, it can't work--the sync block will be different for each boxing of the value.
So if we're telling people never to use lock(this), and we're telling people really never ever pretty please don't use lock(typeof(X)), then what should we say about field-like events and whether you should use them? Well, they are an awfully convenient syntax for something that would ordinarily be a lot of boilerplate code, which is evidently a good thing if we're to judge by the introduction of automatic properties in C# 3.0. Events do seem to be a likely surface area for inter-thread communication. Perhaps that explains why the original language designers settled on this behavior so many years ago. I wasn't on the team at the time, so I can't say.
The title of this post is a joke. I'm not telling you not to use field-like events. However...
If I were writing C# code, and I were a stickler for style and correctness, I would define my own event accessors. There are other reasons to do so, but I'll leave myself something else to talk about in a future post. If I knew about this behavior and didn't care, I wouldn't change anything. And in the meantime, you can make your own decisions about your own code using whatever unique requirements you have for it.