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.

Comments (3)

  1. Anonymous says:

    Given that nothing can inherit from dynamic, "where T : dynamic" doesn’t seem to make any sense. Either C should not have a generic parameter T and should use dynamic instead, or T should not have constraints and the consumer should pass generic.

    As for "U : List<dynamic>", I don’t see any reason why that wouldn’t work.

  2. Anonymous says:

    Nope; that code is invalid. It’s not legal to constrain a generic by dynamic. I would assume this is because it gets compiled down to object.

    If you really want to "inherit" from dynamic you can use System.Dynamic.DynamicObject. This will provide dynamic behavior at runtime.

    I find List<dynamic> interesting. You can put anything you want in there, but it will come back out with dynamic behavior. Your original references remain static. That’s pretty cool.