Omer van Kloeten's .NET Zen

Programming is life, the rest is mere details

News

Omer van Kloeten's Facebook profile

Omer has been professionally developing applications over the past 8 years, both at the IDF’s IT corps and later at the Sela Technology Center, but has had the programming bug ever since he can remember himself.
As a senior developer at NuConomy, a leading web analytics and advertising startup, he leads a wide range of technologies for its flagship products.

Get Firefox


powered by Dapper 

.NET Resources

Articles :: CodeDom

Articles :: nGineer

Culture

Projects

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.

Posted: Oct 29 2008, 02:16 AM by Omer van Kloeten | with 37 comment(s)
Filed under:

Comments

Alex G said:

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?

# October 28, 2008 9:00 PM

Community Blogs said:

PDC PDC 2008 - PDC Pre-Conference: Concurrent and Parallel Programming - Microsoft PDC 2008: Day 1 Wrap

# October 28, 2008 9:30 PM

Larry Smith said:

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.

# October 29, 2008 12:04 AM

Jonathan Allen said:

> 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.

# October 29, 2008 1:48 AM

Alex Bustin said:

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.

# October 29, 2008 2:02 AM

Jonathan Allen said:

> 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.

# October 29, 2008 2:12 AM

Omer van Kloeten said:

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.

# October 29, 2008 2:52 AM

andrew said:

this is why 8 year old's should not be allowed to write programming blogs

# October 29, 2008 3:38 AM

David V said:

<< people used to write in functional languages and some still do... would you you like to go back? >>

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

# October 29, 2008 3:44 AM

Omer van Kloeten said:

Andrew, These are my opinions and you are welcome to express and discuss yours here as well. Derogatory comments aren't discussion.

# October 29, 2008 4:01 AM

Paul Batum said:

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.

# October 29, 2008 6:09 AM

Omer van Kloeten said:

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.

# October 29, 2008 7:10 AM

Craig said:

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.

# October 29, 2008 8:13 AM

Vanja. said:

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?

# October 29, 2008 8:45 AM

IT-Blog » Blog Archive » C# j??zykiem dynamicznym? said:

Pingback from  IT-Blog  &raquo; Blog Archive   &raquo; C# j??zykiem dynamicznym?

# October 29, 2008 10:03 AM

Omer van Kloeten said:

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.

# October 29, 2008 10:16 AM

David Nelson said:

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#.

# October 29, 2008 11:01 AM

rascunho » Blog Archive » links for 2008-10-29 said:

Pingback from  rascunho  &raquo; Blog Archive   &raquo; links for 2008-10-29

# October 29, 2008 4:02 PM

svdeursen said:

I wholeheartedly agree with you! I rather see C# go the verifiable (Spec#) direction instead of the dynamic direction.

# October 29, 2008 5:28 PM

Anay Kamat said:

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.

# October 29, 2008 10:55 PM

Stilgar said:

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?

# October 30, 2008 10:27 AM

Omer van Kloeten said:

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.

# October 30, 2008 11:03 AM

Stilgar said:

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.

# October 30, 2008 11:37 AM

Omer van Kloeten said:

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.

# October 30, 2008 12:25 PM

mnmr said:

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.

# October 31, 2008 8:12 AM

Eran Kampf said:

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....

# October 31, 2008 12:02 PM

Chris Burrows said:

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

# November 1, 2008 2:13 PM

Omer van Kloeten said:

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

# November 1, 2008 2:35 PM

John "Z-Bo" Zabroski said:

@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();

# November 2, 2008 2:33 AM

Omer van Kloeten said:

I can't see why this would pose a problem. After all, IDynamicObject is a CLR interface too.

# November 2, 2008 3:42 AM

Sunday Night Reading « Tales from a Trading Desk said:

Pingback from  Sunday Night Reading &laquo; Tales from a Trading Desk

# November 3, 2008 12:06 AM

Tobi said:

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:

saftsack.fs.uni-bayreuth.de/.../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

# November 3, 2008 3:00 PM

Omer van Kloeten said:

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.

# November 3, 2008 4:21 PM

Tobi said:

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

# November 3, 2008 7:51 PM

Omer van Kloeten said:

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.

# November 4, 2008 12:24 AM

David Nelson said:

"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.

# November 4, 2008 4:24 PM

non-believer said:

"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: en.wikipedia.org/.../Covariance_and_contravariance_(computer_science)

# June 27, 2009 2:25 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)