My View of C# 4.0

I’ve known a bit about C# 4.0 for a while now and have had time to think about it. I’ve just re-read the New features in C# 4.0 paper published by Microsoft and would like to offer the following critique of the language’s new features:

Dynamic Lookup

Microsoft PDC 2008 by Manohar Dasari, CC-BYThis feature just makes me cringe, just like anonymous methods made me cringe when they were introduced in C# 2.0. To this day, I hardly use them, as they always feel like a kludge to me (lambda expressions fixed that).
The dynamic keyword is as open to abuse as anything could be. It takes the principles of static typing and throws the baby out with the bathwater.

What is wrong with it

When looked at initially, the dynamic keyword is great, because it simplifies and speeds up what is usually done with Reflection and Primary Interop Assemblies, both in the aspect of development times and the aspect of run time. Unfortunately, too much of a good thing is bad for you. Imagine the following:

public dynamic GetCustomer()
{
// mystery...
}

What do we have here then? I don’t know and neither does IntelliSense? I guess we’ll have to go with trial and error.
I admit this is quite the dramatization, but you get my point: it’s ripe for abusing an otherwise perfectly fine static syntax.

Moreover, the dynamic keyword’s syntax does what no other feature of C# has ever done – it breaks existing syntax. Should I define in C# 3.0 a type named dynamic, the following piece of code will take a whole different meaning in C# 4.0:

public dynamic GetCustomer()
{
dynamic customer = GetCustomerCOMObject();
return customer;
}
How it can be fixed

Using the dynamic keyword is actually a built-in form of Duck Typing. The idea is good and should be introduced into the language, but I’d like to suggest a different way of doing it:

public ICustomer GetCustomer()
{
dynamic ICustomer customer = GetCustomerCOMObject();
return customer;
}

Here, what I get back is a dynamic dispatch object that must adhere to a specific interface. This means that the object graph is checked for conformity against ICustomer the moment it is cast in the dynamic scope (i.e. returned from GetCustomerCOMObject) and is from this moment on a typed object with dynamic dispatch under the hood. From this moment on, we couldn’t care less about whether this object uses dynamic dispatch or not, since we now treat it as a POCO.
This, along with removing of the ability to send dynamic dispatch objects through the call-stack (as parameters and return types), bringing them to the level of anonymous types, will help stop the deterioration of C# into a dynamic language.

Named and Optional Arguments

Untitled by Long Zheng, CC-BY-NC-SAThis is just silly. Really, this looks like some people cried “we don’t like overloads” hard enough and got some VB into the C# the rest of us liked the way it was. If you want to initialize your method with some of the parameters, use a builder pattern with an object initializer instead.

Here, I’ll take the sample at the bottom of page 6 and fix it, C# 3.0 style:

public void M(int x, MBuilder builder);
public void M(int x)
{
this.M(x, new MBuilder());
}
public class MBuilder
{
public MBuilder() { this.Y = 5; this.Z = 7; }
public int Y { get; set; }
public int Z { get; set; }
}
M(1, new MBuilder { Y = 2, Z = 3 }); // ordinary call of M
M(1, new MBuilder { Y = 2 });        // omitting z – equivalent to M(1, 2, 7)
M(1);                                // omitting both y and z – equivalent to M(1, 5, 7)

Yes, I do realize it’s mainly for COM interop, but most people will just get either confused by all the syntax, abuse it or simply forget it ever existed.

What is wrong with it

It exists.

How it can be fixed

Remove it from C#. There – fixed.
If you want optional parameters in your COM interop calls, just implement the correct overloads in the interface you create for use with the dynamic keyword (see my suggestion for dynamic lookups) and the binding will be done at run time by the parameter names.

Variance, Covariance and Contravariance

These three features are long overdue and finally make an appearance in the language. It’s a great feature and I would love to integrate it into my code as soon as I possibly can.
I would love to know if there are plans to not only include reference conversions, but also the implicit and explicit conversion operators as qualifiers for VC&C.

What is wrong with it

Anders Heilberg at book signing by DBegley, CC-BYAlthough Variance is implicit, the others are explicit. Using the Type<in T> / Type<out T> notation is good for being explicit (for instance when you expect your interface to be expanded in the future), but it doesn’t have to be and can become a bit annoying over time.

How it can be fixed

The compiler can very easily infer the fact that your interface is either input-only or output-only and mark it as such for you. Language-wise, the explicit version should be kept available, for when you want to prevent someone (or yourself) from mistakenly adding a new method that breaks the your input / output only design.

Summary

It looks to me like the team behind C# is going in the wrong direction (DLR) instead of the right direction (Spec#), slowly turning C# into a dynamic language. It looks like all of this is done for the sake of easy interop with dynamic languages and COM objects. It looks as though the designers have succumbed to peer pressure. There are so many features missing from C# and the above are nowhere near the top of my list.

I can only hope someone is listening.

Advertisements

36 thoughts on “My View of C# 4.0

  1. impressive… just because you don’t know how you would use a new feature, doesnt mean it should be removed for everyone else who embraces it.
    just like with anonymous methods that you apparently haven’t figured out how to use, many of us have been using them quite happily and can’t imagine being without.
    yes, named arguments could be replaced with something else… but then, we dont really need classes or objects… people used to write in functional languages and some still do… would you you like to go back?
    MS is unusually forward looking with the .net platform sometimes and pays attention to the programming trends… a lot of these features come from ruby which is gaining a very strong momentum not just because of ror, but because it’s actually a superb language.
    btw… peer pressume is otherwise known as community, and MS can only be praised for listening and following it.
    how about you list your missing features instead of just dissing? you know… everyone’s a critic, how about you be constructive?

  2. Your comments about (semi-) Duck Typing are, sorry, wrong. You assume that a given dynamic object is, well, static, at least from the POV of the methods it has. But the Framework supports (since CLR 2.0), the System.Reflection.Emit.DynamicMethod method, that lets you create new methods at runtime. So a class that’s interrogated for its methods at first reference doesn’t work in this case.
    And I think IronPython and/or IronRuby (and the DLR) support this.

  3. > If you’re want optional parameters in your COM interop calls, just implement the correct overloads in the interface you create for use with the dynamic keyword (see my suggestion for dynamic lookups) and the binding will be done at run time by the parameter names.
    Um, how are you going to add overload to COM? In case you didn’t know, COM doesn’t support overloading.

  4. As an ActionScript 3 developer .. I’d say your overreacting.
    ActionScript 3 also has the dynamic feature ….
    public dynamic class Foo { // dynamic class
    public var bar:* // dynamic var
    }
    And I rarely see them being used. The advantage of using strict typing is just too strong. If I were to ever use dynamic, it would be in a private closure; away from my integration points.

  5. > If you’re want optional parameters in your COM interop calls, just implement the correct overloads in the interface you create for use with the dynamic keyword (see my suggestion for dynamic lookups) and the binding will be done at run time by the parameter names.
    I would like to add that would require 65,536 overloads for Word’s “Open” function. And needless to say, many of those overloads will have identical signatures.

  6. Alex G, I don’t usually say there’s a problem without suggesting a solution. In all of the points I make, a solution is suggested. I dislike named arguments because they cause disarray at the caller’s side.
    MS might be forward looking, but these changes for C# 4.0 seem to be very backward-looking, working to counter the disadvantages of an 18 year old framework (COM).
    My feature suggestions are all available through this blog. Simply click the C# tag and you’ll see a history of suggestions dating back to 2003.
    Larry, I admit I haven’t had much experience with the DLR or DynamicMethod, but I’ll gladly resort to reflection in those cases where you have a living object in your hand and morph it at run-time, as I would with every current version of C#. Since it is not a dynamic language by design, this is an edge case.
    Jonathan, if you look at my suggestion – you’ll see that when using COM objects, you can still use dynamic, but with interfaces. In this case, you will simply code only the method overloads you actually need into the interface and the runtime will check that you actually have all of these overloads implemented. See “How it can be fixed” for “Named and Optional Arguments” in the post.
    Alex B, Abuse is never by those who understand what they’re doing. I’m all for keeping dynamic, but also limiting it by design to private scopes, just like you practice.

  7. <>
    Sorry ? If anything, Functional languages (like ML, Haskell, Clean, OCaml, etc ) seem to be more advanced, not retarded, than what you have there

  8. What is wrong with this post:
    It exists.
    How can it be fixed:
    Remove it from your blog. There – fixed.
    I’m sorry.. I couldn’t help myself. You’ll have to do much better than that if you want anyone to take your ideas seriously.

  9. Paul, I’m very straightforward with expressing my views. I really do think that there is a problem with these features. If you want to address my points, rather than the way I express them, you’re welcome to comment to the point.

  10. Omer,
    I’m glad you are expressing your opinions. While I too am skeptical that these new features will not be used (as in, I know they will be abused), I don’t think that is a good reason to not include them.
    There are great developers who will use these features where they are needed and only when they are needed. There are not so great developers (unfortunately the majority) who will use these features everywhere because it makes their life easier. However, I don’t see the need to punish great developers because other developers are idiots. If we go this route, we will see great developers leaving the platform for something more flexible and that would be incredibly unfortunate.
    So, in summary, don’t let the idiots guide our direction. Hopefully self-preservation will filter out all the crap that is out there and the industry will revolt against those who don’t get it.

  11. I’m a bit undecided on the dynamic variables – I’ll let the COM experts worry about those, but I don’t see how optional parameters can hurt the language.. Sure, you can use the builder pattern (thanks for teaching me something new, by the way!) but why not support something natively?

  12. Craig, I like taking action to prevent future mistakes from happening and one of these things was to offer critique about the new features. My intention was to keep the possible abuse of the language to a minimum, while maintaining these new, very nice features.
    Vanja, I’m just concerned about adding more and more unintuitive syntax to the language. Keywords are usually self-explanatory and syntax is not. This is a duplicate feature of overloading and is only there to appease the COM crowd.

  13. Omer,
    I happen to agree with you for the most part. I doubt I will get any value at all out of the next version of C#, with the possible exception of the variance improvements. I just don’t program in a style which would make use of these new features. The dynamic keyword in particular concerns me, as it is so obviously begging to be abused.
    However, I am also involved enough in the .NET community to know that there are many, many C# developers who WILL get significant value out of these features. And, contrary to your assertion, not just COM developers. One of the goals of .NET is language interoperability, but today interoperating with libraries written in VB.NET from a C# application can be quite cumbersome due to the lack of optional and named parameter support. And doing any kind of Office interoperability is basically out of the question; your only practical choice is to switch to VB.NET.
    I am still not entirely convinced that the benefit outweighs the risk. I would personally much rather the C# team work on making the language more strict with Spec# features than more dynamic. But that doesn’t change the fact that there are a lot of developers whose lives will become a lot easier with the next version of C#.

  14. When I had looked at features provided by Ruby, I was concerned that if this features are used by people who have just started coding, then they might turn it into a mess. Eventually, I figured it out, that new programmers won’t even look at using those features as they would not even understand it.
    To understand the use of these advanced features, you need to have experience. You need to come across a situation, where you have to maintain a duplicate code in methods just because they use objects of different types, but use same properties. This is the time when you really feel need for Duck-Typing or Dynamic keyword.
    Personally, I like to keep code as small as possible. Introducing overloading over methods only to support different count of parameters will simply increase the lines of code. This is where use of methods supporting optional parameters come to rescue.

  15. Interesting… it seems that no one in the comments agrees that the new features should not be introduced into the language. I wonder why. Oh may be because they are good. Also it is strange how the C# team spent years designing this features but you managed to label them bad or dangerous in just a day. It is ok to say that a feature is bad if you had used it and you’ve seen it abused but how are we to believe anything you say when you have not written any code using these features and obviously the C# team has experience in designing programming languages and have tested it with at least some code?
    “most people will just get either confused by all the syntax”
    People who cannot learn the syntax of a language should not be allowed to code in it and people who use features they do not understand should be shot, period.
    oh and BTW I use anonymous methods (I would use lambdas of course but I am stuck with C# 2.0 for some time) more often than I declare interfaces. Shall I requests that interfaces are removed from the language?

  16. Stilgar, I’ll take on your points one by one:
    “it seems that no one in the comments agrees that the new features should not be introduced into the language”
    You should re-read the comments then ;)
    “It is ok to say that a feature is bad if you had used it and you’ve seen it abused”
    And what about using my past experience to deduce it in advance? Is that not a valid means? Am I supposed to sit back and wait until it RTM’s and only then say my piece only to have no one listen to it because it’s already out?
    “obviously the C# team has experience in designing programming languages”
    Does it mean that everyone who has any experience in programming languages think in unison?
    “People […] should not be allowed to code in it and […] should be shot, period.”
    I decided to go with the more subtle approach of prevention.
    “I use anonymous methods (I would use lambdas of course but I am stuck with C# 2.0 for some time) more often than I declare interfaces. Shall I requests that interfaces are removed from the language?”
    You would have been welcome to ask for that when C# 1.0 beta spec was released, although I imagine that without a concrete reason, no one would listen to you. After all, you didn’t give a reason why it shouldn’t be in the language. Oh well.
    Right now you can’t just remove a feature people still use anyway.

  17. My point was that you that even if you are right and the C# team is wrong you just don’t have the time to evaluate it.
    Please point me to the comment that agrees that the features should not be added. Even those that agree with your objections point out that people who need the features should get them despite possibility that they will be abused by underqualified developers.
    I used anonymous methods as an example of something that you “feel” is bad but in fact is not. What if I had “felt” this way before C# 1.0 and now we all had to code without using interfaces?
    What is more I believe that if I try hard I can think of a way to abuse almost every language feature.
    And btw I do not see how your interface based dynamic approach could work with javascript or python interoperability where you can dynamically add and remove methods. It is possible that I do not understand how your suggestion is supposed to work or even how the C# 4.0 proposal is supposed to work.

  18. Stilgar,
    My idea was that you could use an interface to strongly type the calls you can make on that object. If you add a new method, use a different interface to call it.
    I doubt external interfaces from dynamic languages have changing contracts, but it is a possibility.
    I was thinking about suggesting “dynamic var”, which would be just like what the current “dynamic” offers, but is limited to the scope of a method, like var would be. Not entirely sold on the fact that it really is something that needs to be in the language so badly.

  19. It has always been a key goal for the .NET platform to support multiple languages unified within a single type system. Extending the platform to support functional and dynamic paradigms merely broaden the platforms reach and will serve to make integration and interoperability easier. It also allows us to reuse our C# skill sets for when we only want to do rapid prototyping, something that previously would be better served by other languages. Also, Anders was very specific about how these new dynamic language features should not be seen as a move away from statically typed languages.
    Default parameters really should just have been part of C# 1.0. I can’t tell you how tired I am of adding method and especially constructor overloads to make the code easy to consume while keeping it flexible.
    DBC and Spec# will be much easier to implement with the new compiler and language object model planned for C# 5.0, as you get hooks directly into the code generation instead of relying on post-weaving IL into an already generated assembly. We’ll just have to wait a bit.

  20. I wouldn’t call “sending a struct as a constructor parameter” a “builder pattern”…
    Kinda like Optional Arguments…
    It means less code, less complexity and clearer more readable code…
    Yes, you can abuse it and send tens of optional parameters instead of a struct (like they do in other platforms. FYI SAP ESA services…) but you can say that about any feature (LINQ? :))
    Anyway, the real question seems to be around dynamics…
    As much as a dislike dynamic languages, as someone who had to suffer writing managed-to-COM integrations I think this feature is pure blessing.
    I remember having to deal with Office interfaces (Outlooks, “Send To” dialog, the messenger smart tag…) that that were simply un-callable, even when I resorted to all sort of reflection trickery…
    You have to remember that most of the IT world (and Microsoft customers) are still using legacy unmanaged code…
    The adoption of .NET isn’t as wide as Microsoft wanted it to be and it has to take some steps to encourage migration.
    Supporting dynamic languages also means Microsoft is aiming to please them JavaScript, Ruby times… Face it, those guys rule the internet and Microsoft needs them on its side…
    Spec#? that’s enterprisey territory where Microsoft already has a stronger offering…
    As for my battle with Office COM objects? I had to resort to VB where the thing just worked… but it was on VB… if anything should be killed, its VB….

  21. Hi Omer,
    Your comment about the breaking nature of the dynamic syntax is incorrect. The compiler will only bind the typename “dynamic” to the new dynamic type if that typename does not already bind to an existing type in the scope in which you use it. In that sense, it is similar to “var,” which did not break code that used that term already.
    We try to be pretty careful about things like this.
    chris

  22. Hi Chris,
    Thanks for clarifying that. I was a bit worried about it breaking existing strong typing.
    I’d appreciate it if you could refer to the other points I make and my suggestions as well.
    Omer

  23. @Using the dynamic keyword is actually a built-in form of Duck Typing. The idea is good and should be introduced into the language, but I’d like to suggest a different way of doing it:
    So, under your proposal, what does the following compile down to?
    dynamic IDynamicObject myVar = MetaObjectFactory();

  24. Hi Omer,
    actually the feature you requested while talking about dynamic lookups is already possible – even with the CTP.
    The MetaObject is capable of doing all the things you wish for. I wrote a post about IDynamicObject with source code:
    http://saftsack.fs.uni-bayreuth.de/~dun3/archives/first-look-ducktyping-c-4-0-idynamicobject-metaobject/202.html
    If you change the behavior in the “Convert”-Method in “Duck” in a way that would reflect over “action.ToType” and make sure that all methods/properties are implemented or deferable – then your request would be fullfilled I guess? Or did I missunderstand you?
    Cheers,
    Tobi

  25. Hey Tobi,
    Your code is nice, but the reason behind my post was to try and mitigate the possibility of abuse (by someone who didn’t know how to use dynamic correctly), while yours is for those who already know what dynamic is and want to work more statically with it.

  26. Hi Omer,
    oh, I see. But can’t you even use the implementation I used in order to “strongly type” dynamic APIs? Just a thought, I believe I could “hide” behind some type of custom IDynamicObject that I would have to write, in order to check and therefore to kinda strongly type any dynamic API.
    I just don’t care when other shoot themselves in the foot. Just when I step anywhere near them, I tend to wear iron shoes and shin guards. ;) I guess all I am saying is that if you inherit code that abuses dynamics – all regular rules for a brown field refactoring apply. With or without dynamics.
    Or what is the situation you are worried about most concerning dynamic?
    On a completely different note: I am totally with you on named parameters. I don’t care if anybody will use it when accessing my APIs – because I will rename parameters left and right – and if I break your silly named parameter calls to my API I won’t care one simple bit. Come on – method parameter names MUST be private to the method, it’s the only way I can refactor and clarify!
    Cheers,
    Tobi

  27. It’s a good idea if you want to decouple badly written dynamic code from the rest of your code to expose interfaces in the way you suggested.
    My biggest concern is that I will get a 3rd party assembly (or some other code that can’t be changed) that exposes a dynamic value. I can stay out of the way of dynamic for as long as I like, up until that moment when someone forces me to use it in that fashion.
    Good point on the argument naming. IMHO, If I could create overloads by name, that would be the only reason for being able to break code that refers to names.

  28. “Come on – method parameter names MUST be private to the method, it’s the only way I can refactor and clarify!”
    Why? Renaming methods is a breaking change; how is renaming parameters fundamentally different? If you care at all about language interoperability, then changing parameter names is already a breaking change in the .NET world, unless you are just writing off anyone who uses VB.NET. Just because you’ve been doing it and getting away with it doesn’t mean you are doing the right thing.

  29. Omer, I agree with your point of view.
    Let me add another topic: Parallel Extensions and multicore programming.
    As far as I can see Parallel Extensions are always changing… I can’t trust them until Visual Studio 2010 is on the market. Microsoft is pushing developers to use something that is always changing. I can’t develop with something that’s unreliable.
    We must work hard in multithreaded applications until Visual Studio 2010 in on ther market with a Service Pack 1.
    I’ve seen a book recommended in http://www.multicoreinfo.com, books section, C# 2008 and 2005 Threaded Programming: Beginner’s Guide, by Gastón C. Hillar
    I received it yesterday and I can tell you it has a lot of interesting examples for C# developers who want to exploit multicore microprocessors right now using C# 2008.
    http://www.packtpub.com/beginners-guide-for-C-sharp-2008-and-2005-threaded-programming/book
    Highly recommended. I can’t wait for Visual Studio 2010. My Core 2 Quad is laughing using 25% of its power. I want to exploit its full power right now!

  30. “The compiler can very easily infer the fact that your interface is either input-only or output-only and mark it as such for you.”
    I love broad, uneducated statements. How can the compiler do that?
    In fact, it cannot. I think Eric Lippert explained why in his blog. I’ll let you google (or bing if you prefer) yourself, you should do your homework because writing.
    “Although Variance is implicit, the others are explicit”
    Variance doesn’t exisit itself… Only Co- and Contra-variance concepts do (well, Invariant does too, but it’s pretty useless). So I wonder how it can be implicit, while the other twos aren’t. Do you know what you’re talking about? Please have a look a wikipedia for the definition of those: http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)

  31. It’s a strong statement what we see behind the
    implementation the of dynamic, it can’t be sumarised
    like:
    “We want dynamic to be a firts class citizen in our
    c# static world, in the same conditions”.
    It’s a natural, simple amd elegant design. And you have room to implement you own dynamic dispatch.
    These guys knew a litle more about language design than some of us. The implementation you mention it’s more
    “artificial” and it would make the language older. And a team of so many smart guys surely have been around a bunch of differents aproachs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s