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

Comments (22)

  1. Steve Cooper says:

    Being a static-loving guy at heart, I’d like to ‘tame’ dynamic variables as quickly as possible. Will there be a mechanism for something like static duck-typing? So I imagine code like;

       interface IDuck { void Quack(); void Waddle(); }

       IDuck GetMeADuck()

       {

           // get a dynamic variable

           dynamic couldBeADuck = GetDynamicDuck();

           // cast to the IDuck interface, or fail if

           // it doesn’t implement the methods on the interface

           IDuck duck = ouldBeADuck.DynamicCast<IDuck>();

           // It Quacks! It Waddles! it’s a duck!

           return duck;

       }

    This would be particularly useful in scenarios where a COM API has lots of classes inheriting from an unknown base class. For example, if the API exposes these classes in the interop;

     interface Bird { void Eat(); void Move(); }

     interface Fish { void Eat(); void Move(); }

     interface Duck { void Eat(); void Move(); }

    I’d really like to just define an IAnimal interface and assign all three types.

  2. Anonymous says:

    Wouldn’t that just be the same as using Object currently?

  3. Steve Cooper says:

    "Wouldn’t that just be the same as using Object currently?"

    A normal cast only succeeds if the object has been designed to use the type you’re casting to. So generally, casting an object to IAnimal interface will fail, even if the object happens to have Quack() and Waddle() methods.

    My thought is that, with dynamic variables, you could have code that did something like this;

     if (dynamicVar.HasMethod(IDuck.Quack) && dynamicVar.HasMethod(IDuck.Waddle))

     {

       // seems to be a duck

       return new CleverWrapper<IDuck>(dynamicVar);

     }

     else

     {

       throw new InvalidCastException("This is no duck!");

     }

  4. David Nelson says:

    I agree with Steve. This kind of capability is the only way that I can see dynamic capabilities having a real use in a statically typed language such as C#. Unfortunately, in many dynamic languages, objects can have members added and removed at runtime, so querying an object for its members at a specific point in time would be a significant limitation. But without that limitation, dynamic typing as it is being presented here is completely misplaced in a stongly, statically typed language such as C#.

  5. Balls McTavish says:

    As it just so happens, I also really like cheese. I feel personally that, on a scale from one to ten, it is fantastic! I will be voting for cheese this presidential election…

  6. Steve Cooper says:

    @David Nelson

    "Unfortunately, in many dynamic languages, objects can have members added and removed at runtime, so querying an object for its members at a specific point in time would be a significant limitation"

    You’re right — there is a sense in which this kind of casting is pretending to be static typing. However, there’s a class of problems where this is a reasonable thing to do.

    As an example, I’m considering embedding python scripts inside a C# application. Each python item would become a class with a small number of methods; say, Configure() and Execute().

    What I’d like to be able to do is parse a python script to create a dynamic class with these two methods, then cast them to a IScript interface. Because this object is basically stable, the cast is reasonable to do. It’s not guaranteed, of course, but it’s a good start.

  7. I think the dynamic feature is way over the top for the value it provides. As I show here, it is in fact largely possible to implement a terse syntax for making dynamic calls in the current C# language:

    http://incrediblejourneysintotheknown.blogspot.com/2008/05/dynamicobject-wrapper.html

    The difference due to the new built-in feature seems incredibly tiny to me. It mainly consists of totally disguising the dynamic nature of the calls, which I don’t see as a plus.

  8. Welcome to the 47th Community Convergence. We had a very successful trip to PDC this year. In this post

  9. Artazor says:

    It would be a nice transition between dynamic and static programming – if we could write an external explicit implementations of interfaces (something like adapters) that is to separate the implementation of interfaces from the class definition itself. For example:

    class CrazyDuck {

       public void LoudQuack() {…}

       protected void ShutUp() {…}

    }

    interface IDuck {

       void Quack();

    }

    implementation CrazyDuck:IDuck {

       void Quack() {

            try {

                 LoudQuack();

            } cathc(TooLoudException ex) {

                 ShutUp(); // yes, here we should be able to use it!

                 DuckHelper.PerformDefaultQuack();

            }

       }

    }

    After such implementation CrazyDuck class instances should become assignable to IDuck variables. Also I’d propose such a keyword as "interfaceof" that should extract the interface (all public methods, events and properties) of given class. For example:

    class Tiger: interface of Cat {

       …

    }

    or even

    implementation Tiger: interfaceof Cat {

      …    

    }

    this would eliminate a need in corresponing type of refactoring. Also it can be useful to use some constructions for functionality delegation to subitems (like in VB)

    It seems to me that this kind of typing would be more consistent than ordinary duck typing.

  10. Steve Cooper says:

    @Daniel Earwicker

    "it is in fact largely possible to implement a terse syntax for making dynamic calls in the current C# language"

    The example you give makes runtime calls to statically-typed object. It isn’t a call to a dynamic object.

  11. Yes! Add Duck typing into the framework for dynamic types.

  12. Today, let’s geek out about the language design regarding the dynamic type. Type in the language vs.

  13. cburrows says:

    There is no addition to the language that will give you a conversion from some dynamic object to an interface type that it does not actually implement, although you could implement them yourself as Artazor has done. In fact, if you view dynamic as an interop feature, doing this isn’t a bad idea at all.

    Conversions to interfaces are special in the C# language in such a way that would preclude any particular dynamic object from providing these conversions itself, as well.

    I’ll think more about what it means to do this and what we can provide for you, though. Thanks!

  14. curth says:

    I posted a link to a version of the DynamicObject class that will work with the CTP.  It’s at http://blogs.msdn.com/curth/archive/2008/11/07/dynamicobject.aspx

  15. Let’s look at this: dynamic d = null ; object o = d; // not an implicit conversion Last time , I said

  16. Daniel Earwicker says:

    @Steve Cooper

    "The example you give makes runtime calls to statically-typed object. It isn’t a call to a dynamic object."

    The example I give happens to use reflection to make calls to CLR types in its implementation. But it could use the DLR to call dynamic objects, or IDispatch to call COM objects, etc. etc. It could also figure out which of these to use dynamically. The point I’m making is about how the calling code looks: very close to direct method calls, with no need to add further language features.

  17. Or you could just program in Smalltalk. The question is whether your dynamic program will be wonderfully simple, as in Smalltalk, or abusively complex, as in C#.

    It is very interesting to watch the evolution of C# as it recapitulates Lisp and Smalltalk. Language and cultural features that have been around for 30 or 40 years or more, and absorbed a lot of crap from the mainstream cognoscienti for being useless, are now showing up as new and cool. If you really want to see cool, look at and use the originals. They’re much better. This assumption that any real programming language has to a) look like C and b) be strongly typed is something we really need to get over.

  18. Steve Cooper says:

    @Steven T Abell  

    I could never get on with dynamic languages. A good, strongly-typed compiler speeds my up my development no end. Your mileage may vary, but I’ve tried dynamic languages and I’ve found them slower to develop for, and harder to maintain large programs in.

    I think you should keep an eye on C# — the C# team are clearly all mad for advanced, statically-type functional languages like Haskell and ML, and features just keep cropping up. Where languages like Python and Ruby owe their lineage to lisp and smalltalk, C# is, well, the bastard child of Java and ML. And ML is gaining.

    For example, ML-style type inference has made explicit type annotations optional inside C# function bodies. Everything can be declared ‘var’ and nonetheless be strongly typed;

       var i = 0;

       var str = "my string";

       var obj = new Object();

    Lambdas are also nicely integrated, and again use type inference;

       var squares = naturalNumbers.map(i => i * i);

    The equivalent lisp is both more verbose and less typesafe;

       (defparameter squares (map ((lambda i) (* i i)) natural-numbers))

    @Daniel Earwicker

    You’re right — your version could be updated to call DLR or COM objects happily.

  19. @Steve Cooper

    My mileage does vary. The approach differs, the design differs, the debugging differs, and type errors really aren’t a problem very often in good Smalltalk or Lisp. My aversion to type specification is not due to an unwillingness to type, and I understand what can be done with signature matching. I also understand how many problems that are solved by strong typing are caused by strong typing. I prefer languages whose design intent is simple and clear, as opposed to languages that are bags of features. To each his own.

  20. We left off last time with this piece of code public class C { public static void M( int i) { } public

  21. Very good resources for the coming version… Sam Ng Dynamic in C# Part One Dynamic in C# Part Two Chris

  22. It has been a while since I posted anything here, and I have the same excuse everyone else does. Work,