C# 4.0: dynamic ?

I’ve not played with the VS2010 CTP much yet, and I’ve only looked briefly at the documentation and blogs about the new C# 4.0 dynamic type, but a thought occurred to me: why not have the option of making it generic as a way of saying “I will dynamically support this set of operations”?

As an example of what I mean, suppose you have an interface IMessageRouter like this:

public interface IMessageRouter
{
    void Send(string message, string destination);
}

(This is an arbitrary example, by the way. The idea isn’t specifically more suitable for message routing than anything else.)

I may have various implementations, written in various languages (or COM) which support the Send method with those parameters. Some of those implementations actually implement IMessageRouter but some don’t. I’d like to be able to do the following:

dynamic<IMessageRouter> router = GetRouter();

// This is fine (but still invoked dynamically)
router.Send(“message”, “skeet@pobox.com”);
// Compilation error: no such overload
router.Send(“message”, “skeet@pobox.com”, 20);

Intellisense would work, and we’d still have some of the benefits of static typing but without the implementations having to know about your interface. Of course, it would be quite easy to create an implementation of the interface which did exactly this – but now imagine that instead of IMessageRouter we had MessageRouter – a concrete class. In this case the compiler would still restrict the caller to the public API of the class, but it wouldn’t have to be the real class. No checking would be performed by the compiler that your dynamic type actually supported the operations – given that we’re talking about dynamic invocation, that would be impossible to do. It would instead be an “opt-in” restriction the client places on themselves. It could also potentially help with performance – if the binding involved realised that the actual type of the dynamic object natively implemented the interface or was/derived from the class, then no real dynamic calls need be made; just route all directly.

This may all sound a bit fuzzy – I’m extremely sleepy, to be honest – but I think it’s a potentially interesting idea. Thoughts?

Update

Apparently this post wasn’t as clear as it might be. I’m quite happy to keep the currently proposed dynamic type idea as well – I’d like this as an additional way of using dynamic objects.

27 thoughts on “C# 4.0: dynamic ?”

  1. I thought about this myself just yesterday. However, wouldn’t just:

    dynamic router_d = GetRouter();
    IMessageRouter router = (IMessageRouter)router_d;

    /* … */

    work really well here? The compiler can’t check the cast, so it has to assume that it succeeded (if it didn’t, it’d throw an exception at that site) and after that it’ll just assume that router contains a legit IMessageRouter and check those invocations as normal, which is what you want. Since an assignment where the rvalue is a dynamic is supposed to be a run-time dynamic thing as well that throws if it fails, you might not even need the cast.

    My Visual Studio 2010 virtual machine is down and I can’t be bothered to bring it up again, but it seems like it’d work.

    Like

  2. @Jesper: Suppose GetRouter returns something which has all the right methods, but doesn’t actually implement IMessageRouter as an interface. I don’t know of anything in the dynamic handling which would build a proxy interface for you – although I could be wrong, of course.

    Like

  3. Oh, that’s not what I thought you were referring to. I thought you were just saying “I know that I’m getting this object from some mystical place, and since this is duck typing I know that it quacks like a duck in these forms.” and you’d get Intellisense-level smarts for what you could then establish about the object.

    There are some subtle differences here: you retrieve an object that may or may not be a .NET object that may or may not implement IMessageRouter, that you may or may not want to talk into acting as if it did and that you may or may not want to check for the existence of these interface methods and members before you can start assuming that it implements it. I think I know why they didn’t implement that… ;)

    Like

  4. I _think_ I understand what you’re saying, but I’m a bit fuzzy-headed these days myself, so apologies if I missed it.

    Seems like a fine idea, and extra goodness if it’s built into the compiler. But can’t you accomplish nearly the same thing by just making a wrapper type for a dynamic you want to constrain this way? The main thing that would be missing doing it that way would be the potential optimizations the binding system could make, but I think it’d at least address the type-safety part.

    Of course, the final version isn’t out yet but I think it might be too late to add this sort of thing. No harm asking though. :)

    Like

  5. @Jared: Yes, I should probably have mentioned that duck typing was the aim to start with!

    @Nathan: Yes – at least I’d hope so :)

    Like

  6. Jon — I was thinking of precisely this today :)

    I don’t think it’d be too terrible to implement, either. Not great, but not terrible. You’d still need lightweight code generation, and without collectible types that can become a type leak. There could also be issued with partial trust.

    I have code at home that was able to do this back in C#2.

    static class DynamicWrapper where T: interface
    {
    private static Type cachedWrapperType;
    public static T Create(dynamic obj)
    {
    if (cachedWrapperType == null)
    { .. create and cache new type .. }

    return Activator.CreateInstance(cachedWrapperType, new object[] { obj });
    }
    }

    interface IFoo { void FooMethod(); }

    var foo = DynamicWrapper.Create(x);

    foo.FooMethod(); // OK
    foo.BarMethod(); // compilation error

    .. Of course, if you were to go through the bother of LCG, you might as well omit the dynamic bits and create a direct type wrapper when you can, to avoid as much reflection hit as your can.

    Like

  7. Jon, why not just have ‘duck casting’. If the dynamic object provides the methods/properties defined in the interface it can be cast to that interface.

    Right now, this doesn’t work:

    dynamic realRouter = new MessageRouter(); // MessageRouter doesn’t implement IMessageRouter
    // but does have a send(string,string) method.
    IMessageRouter router = realRouter; // compiles, but InvalidCastException is thrown when run

    But it would be cool if it did.

    Mike

    Like

  8. Mike: This would basically be duck casting, but making it really obvious that you’re *expecting* duck casting instead of normal static casting. I’d want to keep the two very separate – C# is still a statically typed language at heart :)

    Like

  9. This could drive developers in creating interfaces that are really never implemented, so they get intellisense and compile time checking. Is this acceptable ?

    What if we get refactoring tool that could create a wrapper around dynamic object based on some inteface. Then we could remove methods we know we will not use or our dynamic object doesn’t have.

    Other idea would be C# syntactic sugar that creates this wrapper for us. Something like delegate keyword that creates class that derives from MulticastDelegate.

    Like

  10. A number of people have been blogging about this. Personally I think it would have been a far better way to go than what has been announced. Unfortunately, in many dynamic languages, members can be added and removed from objects at runtime. So querying an object for its members at a specific point in time would be a significant limitation. However, in my opinion, accepting that limitation would still be far better for the C# language than tossing static typing out the window, which is what the C# team has apparently settled on.

    Like

  11. @David: Static typing hasn’t been “tossed out the window”. What has been “tossed out the window” has been a tremendous amount of reflection pain. The reason that pain exists is because there are things — valuable things that underpin frameworks you almost certainly use — that static typing cannot cope with. The dynamic support addresses part of the pain.

    Like

  12. We’re *almost* to the point of Objective-C’s objc_msgSend(), I think we just need a built in message forwarding mechanism -before- the exception throwing piece is allowed to throw an exception and we’ll be set.

    Like

  13. I was trying to think of a way to do ducktyping to interfaces now we have dynamic; Agreed – this approach as a language feature would be nice. My best effort would be:

    public class DynamicMessageRouter : IMessageRouter
    {
    private dynamic _d;

    public DynamicMessageRouter(dynamic d)
    {
    _d = d;
    }

    public void Send(string message, string destination)
    {
    _d.Send(message, destination);
    }
    }

    Simple enough as a pattern to be codegenned for a given interface, but it’d be nice to have this class available automatically for every interface, without having to code it. Maybe a virtual “inner type” of the interface – IMessageRouter.dynamic ?

    Like

  14. Curt: Were you suggesting that my idea requires the creation of a wrapper object? It certainly wouldn’t. It would be a dynamic object in the normal way, just with the compiler reducing the amount of operations available.

    Like

  15. I’m suggesting that for the purposes of Intellisense and *static* compilation, dynamic would only expose the members of T. In other words, you could have:

    dynamic foo = GetSomeObject();
    foo.Dispose(); // Legal
    foo.RandomMethod(); // Not legal

    However, the actual binding would still be done at execution time – so GetSomeObject() could return something which had a Dispose method, but didn’t know it was implementing IDisposable.

    Like

  16. FYI, a while ago I posted about the idea of a “ducktaper” which is essentially a runtime-generated wrapper object. As Curt comes to say such a wrapper suffers from an identity crisis (you could go off and think of ways to band-aid restore identity to the Equals method extent as you’re controlling the wrapper anyway, but let’s leave that discussion for another time) amongst other defects like piggybacking on interfaces for not-so-good reasons and limitations/caveats from LCG in general.

    More info at http://community.bartdesmet.net/blogs/bart/archive/2008/11/10/introducing-the-c-ducktaper-bridging-the-dynamic-world-with-the-static-world.aspx.

    Thanks,
    -Bart

    Like

  17. I think the dynamic type is there primarily to improve productivity while working with extremely dynamic environment. If you’re working in such an environment, it would take a long time to implement these kind of interfaces. I think your idea is very similar to Java’s checked exceptions (which C# designers don’t like). It will harm productivity without adding significant benefits.

    In addition, it makes false sense of safety. Your code might compile OK and you’ll think it’s not going to fail (since, in C#, you’re used to strong type checks at compile time) while at run time, it’ll throw an exception due to an unresolved method. But when you declare it as “dynamic” alone, you are basically NOT expecting the compiler to do anything for you and you say you’re aware of what you are doing.

    Your idea is very cool in isolation, but considering C# language style, I think it doesn’t fit very well.

    Like

  18. @Mehrdad: With dynamic you’d get Intellisense, and avoid typos which would otherwise only be discovered at execution time. How does that harm productivity?

    Note that I’m not suggesting this would be the *only* type of dynamic dispatch – I’d suggest keeping the “raw” dynamic type as well. If people didn’t find it helped them to be productive, they could just use the raw form.

    As for giving a false sense of safety – the word “dynamic” is still pretty prominent. If that’s not enough of a hint, I don’t know what is :(

    Unfortunately it’s unlikely that we’ll ever be able to see how useful or otherwise it would be – which means both of us are guessing, basically :(

    Like

  19. Yeah, I understand that you didn’t suggest it as the only method for dynamic method dispatch. And I agree we’re all just guessing, but this is how designs work, isn’t it? Nobody knows what’s going happen in the future.

    To clarify what I meant from false sense of safety, it’s really mostly the Intellisense thing. If something shows up in Intellisense, I’ll pretty much believe that it do exist. The specially negative point is, in my opinion, the fact that you might have a couple methods in your interface, one of them exists in the type, the other doesn’t exist. You’ll start debugging, you see it’s successfully cast to dynamic since you can call it’s First() method successfully, but it fails on the Second() method call. I think such a suggestion should only be implemented if member existence is checked at the time of assignment (which is a performance hit).

    Another thing is, C# is not going to be a dynamic language. I think C# developers should stick to static typing as much as possible and use dynamic types when it really helps. I’ll see two situations where dynamic typing is specifically useful, first is COM interop, which usually have much more clutter that you’re able to define interfaces for easily (unless the code is generated by a tool) and they have a lot of pretty useless parameters (for which named parameters exist). The other case which dynamic typing is very useful is interfacing with dynamic languages and dynamic environments. Some dynamic languages support dynamically adding and removing methods at runtime, and I don’t think your idea is suited for them either. After all, if you know enough about the object and use it more than a couple of times in your code (to make it worth declare the interface), static typing is probably the way to go. This feature might unnecessarily make people go for dynamic typing, which C# designers are probably going to avoid.

    I personally think Intellisense is and should be the smartness of the IDE, not the language. I should not manually hint VS to show intellisense for me. If this is merely to help VS, I think it’s better be a special type of comment rather than a syntactic thing that compiler understands. VS should be designed to support C# well, not the other way around.

    That’s just my personal opinion. I’m not a language designer and you probably have a lot more experience in this area.

    Like

  20. I have thought this would be the first “dynamic” step c# would go in but I guess they are trying to target python type dynamic users rather that give c#ers what dynamics they want.
    I thought you should declare it like this

    public dynamic interface IMessageRouter
    {
    void Send(string message, string destination);
    }

    and then use it as a normal interface with “is” and “as” keywords but no type ever needs to derive from it. and if the dynamic interface doesnt match it is just null. Easy to handle and easy to learn.
    Thats my two cents on Duck Typing in C#

    Like

Leave a comment