Why Doesn’t C# Implement "Top Level" Methods?


C# requires that every method be in some class, even if it is a static method in a static class in the global namespace. Other languages allow “top level” functions. A recent stackoverflow post asks why that is.

I am asked “why doesn’t C# implement feature X?” all the time. The answer is always the same: because no one ever designed, specified, implemented, tested, documented and shipped that feature. All six of those things are necessary to make a feature happen. All of them cost huge amounts of time, effort and money. Features are not cheap, and we try very hard to make sure that we are only shipping those features which give the best possible benefits to our users given our constrained time, effort and money budgets.

I understand that such a general answer probably does not address the specific question.

In this particular case, the clear user benefit was in the past not large enough to justify the complications to the language which would ensue. By restricting how different language entities nest inside each other we (1) restrict legal programs to be in a common, easily understood style, and (2) make it possible to define “identifier lookup” rules which are comprehensible, specifiable, implementable, testable and documentable.

By restricting method bodies to always be inside a struct or class, we make it easier to reason about the meaning of an unqualified identifier used in an invocation context; such a thing is always an invocable member of the current type (or a base type). 

Now, JScript.NET has this feature. (And in fact, JScript.NET goes even further; you can have program statements “at the top level” too.) A reasonable question is “why is this feature good for JScript but bad for C#?”

First off, I reject the premise that the feature is “bad” for C#. The feature might well be good for C#, just not good enough compared to its costs (and to the opportunity cost of doing that feature instead of a more valuable feature.) The feature might become good enough for C# if its costs are lowered, or if the compelling benefit to customers becomes higher.

Second, the question assumes that the feature is good for JScript.NET. Why is it good for JScript.NET?

It’s good for JScript.NET because JScript.NET was designed to be a “scripty” language as well as a “large-scale development” language. “JScript classic”‘s original design as a scripting language requires that “a one-line program actually be one line”. If your intention is to make a language that allows for rapid development of short, simple scripts by novice developers then you want to minimize the amount of “ritual incantations” that must happen in every program. In JScript you do not want to have to start with a bunch of using clauses and define a class and then put stuff in the class and have a Main routine and blah blah blah, all this ritual just to get Hello World running.

C# was designed to be a large-scale application development language geared towards pro devs from day one; it was never intended to be a scripting language. It’s design therefore encourages enforcing the immediate organization of even small chunks of code into components. C# is a component-oriented language. We therefore want to encourage programming in a component-based style and discourage features that work against that style.

This is changing. “REPL” languages like F#, long popular in academia, are increasing in popularity in industry. There’s a renewed interest in “scripty” application programmability via tools like Visual Studio Tools for Applications. These forces cause us to re-evaluate whether “a one line program is one line” is a sensible goal for hypothetical future versions of C#. Hitherto it has been an explicit non-goal of the language design.

(As always, whenever I discuss the hypothetical “next version of C#”, keep in mind that we have not announced any next version, that it might never happen, and that it is utterly premature to think about feature sets or schedules. All speculation about future versions of unannounced products should be taken as “for entertainment purposes only” musings, not as promises about future offerings.)

We are therefore considering adding this feature to a hypothetical future version of C#, in order to better support “scripty” scenarios and REPL evaluation. When the existence of powerful new tools is predicated upon the existence of language features, that is points towards getting the language features done.

UPDATE: More thoughts on considerations motivating this potential change here.

Comments (58)

  1. That’s very good news (not that it’s officially news! I get that! But if it ever does happen it would be great).

  2. Konrad says:

    I’m not sure this answers the question and/or many potential use cases. Scripty programming is all very nice – but frankly, I don’t need C# for that. No, the top objection to this restriction that I have is that there’s often no logical connection between (static helper) classes and their static methods. They simply serve as organization units – but this job is usually done by namespaces in .NET.

    Your point is essentially that C# forces the organization of code into components, but not all code logically fits into a particular component. I agree that this is the case. This is always the case in programming languages; not all possible code fits into the “object” paradigm, the “component” paradigm, the “function” paradigm, the “imperative” paradigm, the “declarative” paradigm, and so on. The question at hand for the language designers is: given that we believe there is value in component-oriented programming, how many tools do we want to give the user that allow them to work against those design goals when they are in one of those situations that meshes poorly with that paradigm? That’s a judgement call; the benefit has to be pretty high in order to be worth bending one of the core principles of the language design. — Eric 

    Furthermore, this restricton prevents the use of static methods directly, without prefixing them with a (logically unrelated) class name. Both Java and VB.NET allow this (albeit using very different ways, the first by importing members of a class, the second one via modules).

    Finally, extension methods have *partially* mitigated this problem – but still, in many cases free functions are syntactically superior to methods.

  3. TheCPUWizard says:

    I have to vote strongly againt this idea. Within an Object Oriented environment, everything should be bound to a Type or an Instance of said type.

    If you allow for "free" functions, then to be consistant you need free variables (and properties). This makes Pandora’s box seem like a "good" idea.

    [Eric, I know you have heard this from me before…]

    Attempting to make C# (or any language) be "one size fits all" is doomed to failure and in the process will make the language harder to use for the exact purposes it was created.

    The "extension" point should be the .NET environment; which is exactly what it was created for. If a project can benefit from using multiple design techniques; then use multiple programming languages.

    Even if the budget and resources were unlimited [reducing the development cost to 0 for any possible feature], this (extending capabilities by multiple languages) would still be my preferred way to go….

  4. Joel Coehoorn says:

    I see this as a feature that lends itself to abuse.  Now, I know it’s just a tool, and as with any tool the use or mis-use of it depends on who’s holding it.  But I think this would be a tool that _encourages_ abuse.  It’s not something I would want to see in the language proper.

    What I _would_ like is a "C# for Scripters" product.  And it should be a completely separate product, or maybe just a different project type in visual studio.  It would include better access to the WMI libraries (System.Management imported by default, and more strongly-typed classes added to it), support to make it easy to automate other programs (easily click a button or modify a textbox based on active window, process, or screen coordinates, and getting said process handles, windows, etc), and it would be something you can just start up (and it should start _very_ quickly) and start entering code.  This would also be useful as a scratchpad environment for "normal" programming.

  5. Jason says:

    *Strongly* agree with TheCPUWizard. If people want or need a scripty version of C# (which is completely understandable), let them use F# or VB. You are slowly turning C#  into C++ in terms of being overcomplicated with a thousand ways to shoot yourself in the foot. You hit the sweet spot (ease of use / power / readability) with C# 2.0.

  6. TheCPUWizard said: "I have to vote strongly againt this idea. Within an Object Oriented environment, everything should be bound to a Type or an Instance of said type."

    Try thinking about it this way: a static method inside a class is really just a global method with a dot in its name.

    If that makes it ‘Object Oriented’, then apparently ‘Object Oriented’ means very little!

    Furthermore, it is frequently a minor implementation decision between writing a simple helper class or writing a method, especially with the existence of delegates, anon-methods/lambdas and iterators. An iterator method is in some ways a class declaration – it defines an object type implementing a state machine. So the line between classes and methods is somewhat blurred.

    If Enumerable.Range was written as a class:

    public class Range : IEnumerable

    Then it would be allowed to go in a namespace. But as it’s been implemented as a method, it’s not. So it has to have a name with a dot in it.

    And namespaces clearly overlap a great deal conceptually with static classes; one difference is that the same namespace can be contributed by code in different assemblies, but nevertheless it is odd that both exist if you ignore the historical evolution of the language and platform (which of course can’t be ignored in reality).

  7. Jason says:

    It is less about being object-oriented and more about being organized, especially in environments with multiple developers. If people can throw functions into the root namespace (say, CompanyName.) people will, and that will be detrimental to placing methods into the proper components where they make sense  (even for the cases where it is not always clear where a method belongs and/or might make sense in multiple classes).  

  8. pminaev says:

    To all people complaining that global methods are not object-oriented enough, or pollute namespaces.

    Open a big project that you work on. Search for files named "Utility.cs" (or "StaticMethods.cs", or "Helpers.cs") in the tree. Count the number of files found.

    Now, stop and think about it for a moment. Do you seriously claim that, by prefixing every static method with "Utility.", you 1) actually reduce scope pollution in any meaningful way, and; 2) make the code object-oriented?

    OOP is about classes _and objects_. "Static classes" are a weird artifact of the simplification that many languages – including C# – make by only allowing classes at top level. They have absolutely no correspondence in object-oriented design theory; ultimately, they’re just a hack. Granted, it’s the one that simplifies language implementations and tools, and (perhaps) makes the language itself slightly more regular and thus easier to learn, so we go along with that.

    Now as for scope pollution – it is precisely what namespaces are for. No-one is talking about shoving methods into global namespace (besides, you can do it with types alread anyway). The idea is that e.g. System.Math should ideally be a namespace, not a type – so that you can import it, and directly use the functions within. Obviously, there’s no scope pollution involved – the functions are still confined to their specialized namespace.

  9. TheCPUWizard says:

    Lets use pmnieav’s example of System.Math.  It not only contains Methods it also contains (const) Fields. This directly supports my previous position on the effects of consistantly supporting "naked" functions.

    Even more importantly, the class has two PRIVATE items [maxRoundingDigita and roundPower10Couple], to tansform this functionallity you would need to further complicate the structure of the language.

    I ask every one to remember OCcam’s razor, and also Scott Meyer’s time tested advice – "Don’t MolleCoddle your users!!!" – give them ONE way to accomplish a task – choices with no cllear distinction as to which is appropriate for a given situation COSTS MONEY in every program that is developed using that tool (language). In other words, every time a feature is added to the language [any language] it incrementally increases the cost of developing ANY program using that language.

    I tend to agree with Jason that (from a language perspective) C# 2.0 really did hit the "sweet spot"; the BCL additions that make up 3.0 and 3.5 are extremely valuable, but are not language issues per se…

  10. commongenius says:

    @pminaev,

    The fact that most developers don’t bother to think about the appropriate structure of their program and tend to just shove everything into a god class (the VB application I am currently maintaining calls it modMain) is NOT a valid argument for allowing top-level methods. It just means that most developers are lazy, and I am not in favor of taking laziness into account when designing a professional language.

    I also strongly agree with TheCPUWizard. A huge amount of effort has gone into making it easy to interoperate between multiple languages on the .NET platform, which means it is trivial (in most cases) to use the right language for your situation while still taking advantage of all of the great features and libraries of .NET. Yet we still hear developers clamoring for <their favorite language> to get <feature X> so that it will be easier for them to implement <something for which the language was not designed> without having to learn anything new. The inevitable result of this effort to toss everything into the same bucket is a bloated language which topples under its own weight; all you have to do to see this effect is look at C++.

    In short, lets PLEASE keep C# component-oriented, and leave other competing design goals to other languages. I really don’t want to have to abandon C# in five years because it has become to heavy; we are already way too close to that point.

  11. ShuggyCoUk says:

    I would just like the f# repl to become much stronger and easier to use…

    Making it easier for all referenced projects to be automatically loaded for example, or to cancel a running command without having to kill the session (and all associated state)

  12. Matthew Kane says:

    Yuck! My reasons have all been given by others in previous posts.

  13. Strilanc says:

    Visual Basic supports this in two different ways: modules and global imports.

    VB Modules are static classes which can have their functions called without specifying the module name. I don’t like this behaviour because it puts the methods in two places at once (F and M.F).

    Global imports I do like. They are properties you set at the solution level, and act as an implicit imports (C# using) line at the top of each source file. This way VB source files don’t all start with the same half dozen import statements.

    VB also has another feature related to this which C# doesn’t have. If you’ve imported the System namespace, you don’t need to include it when referring to classes in sub-namespaces (eg. Numerics.BigInteger instead of System.Numerics.BigInteger).

  14. Weeble says:

    One perceived problem with having such top-level functions is that they will proliferate and it will become very hard (at least without relying heavily on the IDE) to tell where any given name is resolved to. However, that is already a problem with types. I find it a shame that in C# it’s easy to import the entire contents of a namespace but hard to import individual names from that namespace. (You can do "using TextWriter=System.IO.TextWriter;", but it is a bit clunky and generally refactoring tools won’t help you to write code like this.) It is the default "import everything from the namespace" using directive that makes it hard to tell where all the names resolve to.

    Personally I quite like Python’s "from package import name1, name2, name3". This manages to be relatively succinct while remaining quite unambiguous about exactly which names from the package we’re using. Conversely, it lets you know when you see those names in the file which package they came from.

    I wonder if top-level functions would be more palatable to some if the convention had historically been to use explicit using aliases and to avoid using entire namespaces. I guess we’ll never know – there doesn’t seem much can be done at this point. Even though I’d like a nicer syntax for explicitly using individual types *without* renaming them, any such change has so little benefit over standard "using aliases" that it could never claw its way into positive points.

  15. ShadowChaser says:

    "We are therefore considering adding this feature to a hypothetical future version of C#,"

    Was that hypothetical, or a real consideration?

    In all honesty, the fact C# enforced method encapsulation inside classes is one of the things I like the most about it. C# is relatively "clean, pure, and simple" compared other languages – please keep it that way.

    Isn’t that why Visual Studio contains other languages? I’d hate for the C# language to become a cluttered, horrible mess just for the sake of "progress".

    Strong vote against this change!

  16. Delmania says:

    I just want to echo some of the sentiments here.  The benefits of scripting languages have been proven with Ericsson’s derivation of Haskell and CCP’s usage of Stackless Python in Eve Online.  But in both cases, however, a part of that sucess is because those languages were developed, from the get go, to be scripting languages.  C# is more along the lines of C++, Eiffel, and Java.  It’s better to keep the original design that has been through 4 iterations then to try and change it.  If Microsoft wants to enter into the REPL language market, it would be better to devote reources to F# or just create .NET bindings for Haskell.

  17. John Melville says:

    I guess I’m just joining the chorus, but — please don’t do this to C#.

    Strongly agree with the CPU wizzard, please don’t make C# something its not, make it easier to interop with everything else.  (Just like the dynamic keyword makes it easy to call into dynamic languages without surrendering and becomming dynamic ourselves.)

    Now that there are actually several genuinely distinct .NET languages out there, the next innovation needs to be in the project system.  I would like to be able to include a F# class in my C# project, or even an F# method in my c# class.  Assemblies can’t have circular dependencies, so just having two projects doesn’t make it easy enough to elect a different language for a single class, I might have to re-factor my entire project structure to get all the dependencies to all the right classes with no cycles in the graph.

    I think that the pressure to make C# more like everyone else would be a lot less if I could easially decide "language X is the most natural expression of this concept" and go from there.

  18. Ben Voigt [C++ MVP] says:

    I agree with pmnieav that this is the singular distinction between static classes and namespaces, and that putting Math. in front of Sin, Cos, Abs, etc is just silly.  I don’t think the answer is free functions.

    Provide a "static using" directive to introduce static members and subtypes of any class into the name resolution search space, make it be usable within methods as well as within types (don’t need it file-wide), and there would no longer be any need for namespaces as a separate concept.

    Namespaces as a separate concept are dangerous anyway.  They don’t respect visibility (can’t be declared internal, stretch across assembly boundaries) and don’t provide anything static classes don’t, except at the level of syntactic sugar (the namespace name is optional when a using directive is in effect).

    The significant advantages of "static using" are:

    – it improves access to existing libraries

    – namespace pollution is explicitly opt-in, unlike free methods and to a greater degree than extension methods

    – visibility

    – generics

    Oh, I would also require a fully qualified name with "static using", no combinations with either "using" or earlier "static using" directives.

    And haven’t we had this discussion before?

  19. I do not see a benefit even in static using, given that we have extension methods. Forced static imports of modules is one of the reasons I do not use VB anymore.

    I think there is much more important stuff that can make people’s lifes simpler, "yield foreach" is one (small) example. Allowing global level methods, on the other hand, gives nothing a tool can’t give just by transparently wrapping code int o a class. For example, when you create C# extension functions in XSLT, you do not have to create a class, XSLT compiler does that for you.

  20. Stefan Wenig says:

    @daniel:

    > Try thinking about it this way: a static method inside a class is really just a global method with a dot in its name.

    Except that it’s not. The class provides scoping, context, and it can be imported using an alias. Utility.Foo and Utility.Bar will conflict if they are in two different classes.

    Sometimes you can find a useful class that actually provides context and makes those methods more easily discoverable. Sometimes you can work around it using extension methods (including some cases where you should not). Sometimes it’s just getting in your way. At least it makes you think more about where to put it. And it provides a smell for code reviews. As long as you don’t slide into procedural programming, it’s only a minor annoyance.

    Given all the pro’s and con’s, I find it hard to justify putting effort into this. There are far more pressing features that would actually effect our daily development tasks (how about the hypothetical metaprogramming features of that hypothetical next version BTW? they are so hard to justify if you just count votes and ignore the fact that the few developers asking for them provide frameworks for so many others…)

    REPLs are going to need some additional stuff anyway, like ad-hoc variables. I don’t see why any of that should be included in the "compiled edition" too.

  21. Ollie Riches says:

    It feels like you’re about to Jump the Shark…

  22. Weeble says:

    I like the idea of "static using" as described by Ben. I find that more desirable than having the functions themselves be free. That would solve the Maths.Sin problem without requiring any new maths API. I realise that I really don’t object to the fact that the static methods live inside a static class, I just object to having maths-related code cluttered up with "Maths." all over the place.

    I don’t see how extension methods reduce the marginal value of "static using". I really don’t think "x.Sin()" is an improvement over "Maths.Sin(x)", and the idea of "y.Atan2(x)" is terrifying.

  23. Gavin Greig says:

    I agree with the majority of previous responders in my hope that this doesn’t advance into positive points for implementation; and while I’m at it would second Stefan’s interest in metaprogramming.

  24. @ShadowChaser

    "Isn’t that why Visual Studio contains other languages? I’d hate for the C# language to become a cluttered, horrible mess just for the sake of ‘progress’.

    Strong vote against this change!"

    I completely agree with you ShadowChaser.  C# is good at being C#, there’s no reason to try to make it do all of these things that other languages do.  It will only lead to the language becoming cluttered (much like VB).

    I don’t want C# to become like VB or JScript or any other language.  I’d use a different language if I needed a feature that desperately, that’s why other languages exist.

    I’m not saying that the C# team should stop developing new features, I’d just like them do develop features that naturally fit in and are "in keeping" with the language.  This would keep the language consistent and the features intuitive.

  25. Jason Haley says:

    Interesting Finds: June 23, 2009

  26. rafaelromao says:

    I really can’t see this as a good thing. And I’ll be very disapointed if I see this feature in a future version of C#. I don’t want to have to tame my developers to don’t do a completly mess again, as they did in the Delphi era. Top level functions leads to a completly messy and almost unmanageable/understandable code.

    If one wants a scripty language, choose another one, not C#.

  27. Thomas Krause says:

    While I do not strongly disagree with adding this feature to the language, I don’t see a big benefit for it either.

    In my projects I would not use this feature, because I like to use (static) classes to organize my "global" functions. I usually have no problem coming up with a name for these classes, since you can organize almost any function with a simple Noun.Verb-scheme. This has the benefit, that I can see at the call site which class (and file, see below) the function belongs to and can quickly navigate there.

    It is also a matter of organizing the project. Usually I have one file per class. With global methods, would I put all methods in one big Global.cs, or even one function per file?

    So for any larger project, I don’t really see how this would help me. And making the language more complex, with no (or minimal) benefit is always bad. If you need to add something to support "global" functions, maybe extending the using clause to let us import static members of static classes would be an alternative, although I wouldn’t use that feature in my projects either.

    The only real use case for this feature in my eyes is for embedding C# as a scripting language in other applications. I have done this a few times and you can do a lot with a combination of sub classing and adding class constructs and using-statements automatically to the code the user entered. But this is of course fragile and I can see a real benefit here.

    However for these scenarios, it would be even more useful to me if we had an extensible compiler pipeline like boo, so that we can modify the compiler itself for the specific scenario we need to support. I believe I’ve read somewhere that the compiler team is already working on something like this while they’re also rewriting the C# compiler in C#. Do you have any more information on this Eric?

  28. JT says:

    I will stop programming in C# or .NET -once Microsoft tries to take this kind of direction.

    It not only sounds crazy but it is like going backwards. Saying that C# need to match

    other langugage features etc is just not right. I hope Microsoft will put people with OOP

    background in C# team -not people with scripting background – as in charge  

  29. LA.NET [EN] says:

    Another interesting post by the great Eric Lippert .

  30. ASPInsiders says:

    Another interesting post by the great Eric Lippert .

  31. HA HA HA says:

    C# doesn’t need top-level functions, though I do occasionally miss them.

    What creeps me out here is (if I understand you correctly) the prospect of anything remotely REPL-ish going into C#. You don’t bolt a bathtub onto a motorcycle just because somebody, somewhere, might need a place to raise rabbits. Look at C++. Just, just LOOK at C++. I love C++, but holy Toledo, it’s not a design to emulate. People spend years thinking in C++ all day every day and still get blind-sided by weird stuff.

    Language design should to some degree proceed by accretion and trial and error, just like the design of any tool. It’ll never be an exact science and there’ll always be room for improvement. But you have to beware of the point where you evolve a hammer into a circular saw/screwdriver, and then your wife wants a nail clipper, and you start thinking you should do it by adding more features to your circularhammersawdriver, just because you’ve put so much time into it already.

    Sorry, that reads like Spolsky on a caffeine jag…

  32. pete.d says:

    "Furthermore, this restricton prevents the use of static methods directly, without prefixing them with a (logically unrelated) class name. Both Java and VB.NET allow this"

    Not to suggest that this would be relevant anyway (the "language X does it, so C# should" argument is flawed to start with), but it’s not true that Java allows this.  You can import a class from a package, or even all classes from a package, but you still need to provide the class name when referencing the class or members.

    No doubt Eric is already aware of this, and of course it’s not really relevant to the question anyway (wisely, not one of the six criteria involved in the question of whether to do a feature or not has anything to do with what other languages do)

    As far as this goes:

    "Open a big project that you work on. Search for files named "Utility.cs" (or "StaticMethods.cs", or "Helpers.cs") in the tree. Count the number of files found."

    I only have classes like that when it’s a small, "rough-cut" program and just a handful of these kinds of "no-man’s land" methods.  Otherwise, these kinds of methods do wind up in specific static classes for the purpose of organization.

    Could one accomplish something similar by simply putting them into a namespace, and not requiring that they group into a class?  Sure, I suppose so.  But why?  In what way does that significantly benefit my code?  It doesn’t.  It’s trivial to type the correct class name to qualify the method, and doing so actually makes the code a bit more clear.  If I’m skimming through the code, it’s nice to have immediate indication (for example) that I’m calling the Truncate() that will return the integer portion of a number rather than the Truncate() that resets the file length to 0.

    Sure, with additional analysis one could probably still figure out the difference in such cases without too much trouble, but a) every exception to that generality argues against top-level methods, and b) for these kinds of static methods, the code is still easier to understand when it’s more explicit, even as it’s possible to decipher it even if the class/namespace name isn’t explicit.

  33. pminaev says:

    Wow! I would never have thought that a rather innocent suggestion of adding top-level functions to the language could evolve into a flamefest worse than the one over "dynamic". It’s interesting to observe where the priorities of C# coder lie, but that’s quite unexpected to me. Go figure…

  34. AB says:

    >>"Furthermore, this restricton prevents the use of static methods directly, without prefixing them with a (logically unrelated) class name. Both Java and VB.NET allow this"

    > Not to suggest that this would be relevant anyway (the "language X does it, so C# should" argument is flawed to start with), but it’s not true that Java allows this.  You can import a class from a package, or even all classes from a package, but you still need to provide the class name when referencing the class or members.

    While agreeing that Java’s semantics are irrelevant to C#, note that ‘import static’ appeared in Java SE 5.0, see http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html.

  35. pete.d says:

    "flamefest"?

    Huh?

    I’d say of people stating "more emphatic" opinions one way or the other, you’ve essentially got parity.  And many responses (including mine) are more along the lines of "it could be marginally useful, but there are much better things the language designers could be doing with their time".

    Come on…I’m sorry not everyone agrees with you 100% on the matter, but to characterize the comments as a "flamefest" is absurd.  It’s been a very civil discussion, and if this is a worse disagreement than that which occurred with "dynamic", I’d say "dynamic" must’ve gotten a pretty warm reception.

  36. pete.d says:

    "note that ‘import static’ appeared in Java SE 5.0, see http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html.&quot;

    Ah.  That’ll teach me to stay up-to-date.  :)  Thanks.

    Still, I note even in that reference, they strongly advocate avoiding the use of the construct except in very narrow circumstances.  I’d say in the "should this feature exist" point system, a feature that requires a warning like that would probably start off with -200 points instead of the usual -100.  :)

  37. C# fan says:

    +1 for not doing it.

    Especially not just because it is "trendy". Trends are often overrated and don’t necessarily last for long.

    I’d say if you want a truely competitive REPL or scripting language you’ll need several other important changes to the language. If that’s your goal, maybe it would be best to have a new language spinoff, say CScript?

    Although I love my C#3 being so much more expressive and productive (esp. thanks to the LINQ APIs and the lambdas), I can’t help but think it is headed toward the bad direction. Each iteration of the language becomes more complex, soon _too_ complex. Extensions method surely aren’t good OO-design, it is my understanding that they are mostly there to make the LINQ machinery work. Anders had explained why he ruled out default parameters from C#, now they are finally there in C#4…

    If you need ideas for next version, here’s one, which even happens to be trendy:

    Make asynchronous continuations easier. You need to write so much unreadable code, just to call a webservice asynchronously and handle its response (webservice being just an example). F# "async" workflows are pure genius and I’m very jealous for not having something similar in C#.

    As someone suggested, if languages were better integrated in Visual Studio (i.e. one could write files in different languages in the same project) that would be awesome.

  38. Todd Wilder says:

    Why do I always hear C# has such a constrained budget and that future versions may or may not happen? This has been a recurring theme in your posts. Is C# gonna be axed soon?

  39. TheCPUWizard says:

    Todd,

    EVERYTHING has a constrained budget, and I think the development team at Microsoft (not just C# but the entire division) has been very open about the circumstances.

  40. Joku says:

    I have scripting background before coming to C#. I’d really love the ability to be scripty (WITH good intellisense, unlike most scripty languages). I’d go as far as replace powershell with a C# command line while keeping the C# perf and adding some usual command line aliases to c# code. I just don’t dig powershell syntax and I believe you could accomplish the powershell style of tasks with c# with just as little typing if there was suitable functionality in the framework and intellisense was heavily used.

    However I also agree with the concerns represented here. C# programs just look cleaner as there’s some structure and organization there always.

    I think there has to be some kind of ‘best of both’ approach and maybe you should make a post suggesting some and also offer readers a chance to discuss and suggest their own.

    I believe that at somepoint, the cost of adding new stuff while keeping existing users happy will start to either impede progress or have some other negative effects. Even just perceived, not real, negative effects could hurt language in the long run and I believe that’s something MS needs to consider.

    What I’d consider is to at some point branch the C# language such that the language reciding in .cs files gets only minor upgrades if absolutely necessary and the new developments would go into files with new file extension with strong IDE support such as ability to perfectly convert old code to whatever modifications were made that broke backward compat in the branch. That’s also where I’d put these top level methods.

  41. Joku says:

    Oh and I have to suggest a name for the C# branch: C# Next Generation. LOL

  42. TheCPUWizard says:

    Joku,

    1) "best of both" is alsmost always an impossible goal in any area. If something can be used for "A" and for "B", then it is alomst inevitable that adding the support for "B" has imposed some constraints on the implementation of "A" (along with the reverse).

    2)  "the cost of adding new stuff" always exists. Hopefully the positive effect significantly outweighs the negative effect. Consider a situation where I hire four coders who each know 95% of version "n". statistically, up to 15% of the code base that gets developed can not be effectively maintained by randomly assigning it to a programmer.  

    If the language capabilities expand by 10%, then it is likely that the average percentage of knowledge/experience will drop. Initially this will be because few people know the new stuff. This is not so bad of an impact because existing codebases will tend to consist of the older established capabilities.

    But, over time the difference between old and new will fade. Unfortunately history has shown that the amount of work people invest before considering themselves "competent" remains about the same. This results in the average candidte knowing a smaller subset, and the subsets between different candidates diverging.

    At this point, putting together a team of four is statistically going to have the probability that over 35% of the codebase may contains some feature that a given team member is not familiar with.

    disclaimer: the numbers used are mathematically valid, but make "worst case" assumptions; they also get worse as the size of a team increases. In my 25+ years working as a consultant involved with various teams of all levels, I have found this principal to hold true.

    There are some management steps which can be taken to mitigate this effect, but they typically run into one of two problems. Some constraints can be very difficult to enforce in an automated way. Other times certain "excluded" items present a compelling case (for the team member who are knowledgable about the item).

  43. Jon says:

    I just want to say that I think adding global methods would be a horrible idea. Please don’t put them in there. I don’t want to go back to the old days of C where programmers putting everything in global variables and the code is impossible to read. Don’t go making it like JavaScript either. I want strongly typed objects.

  44. Stephen Stewart says:

        I agree with the "don’t add this" crowd.  This feels to me like a technological solution to accomodate a combination of laziness (not creating logical places for the code) and style differences (those who don’t like Class.Method), both of which are human problems.

    I like most of the reasoning against it, but I think that one important example has been overlooked, the cleanup of code to make it more readable for people that do not like to have StaticClassName.StaticMethodName everywhere, and that is to write a local wrapper method, or better yet, have Visual Studio do it for you.  In the below sample, I used Refactor, Extract Method on Math.Sin(s), which created a private static method, which can now be called within the current class.  You can remove the static from the local Sin method as well.

           private void GetSinOfZero()

           {

               double s = 0;

               // Original line :

               // s = Math.Sin(s);

               s = Sin(s);

               this.Text = s.ToString("0.0000");

           }

           private static double Sin(double s)

           {

               return Math.Sin(s);

           }

        I think that this is a "Best of Both" solution using the tools that are already in C#.  It keeps the calling code readable, and if you need to see the true method invocation, it is right there for you.  I believe that the compiler is smart enough to see that the wrapper is just that and directly wire up the code as if it were a direct call to Math.Sin, so performance should not be an issue.

        The downside to this is that you need to create new method wrappers for each class, but that is easy to do and easy to put into a central location where commonly used ones can just be copied and pasted.  You could probably even automate that by using partial classes and adding a T4 template that includes a common set of wrappers for each class that you want to have them, reading them from a central file, if you really feel the need to do that.

  45. Mark Sowul says:

    Another vote for keeping it simple.  I do love lambda expressions, so there’s no way I’d say C# 2.0 was the best, but please don’t tack on everything.  If you add every feature from every other .NET language, then what exactly is the point of all the interoperability?

  46. pminaev says:

    @pete.d

    I’m sorry if anyone was offended by my "flamefest" label, but I stand by it. There were a number of comments that cannot be defined as anything but. For example:

    > I’d hate for the C# language to become a cluttered, horrible mess just for the sake of "progress".

    (actually, that whole comment was like that)

    > I will stop programming in C# or .NET -once Microsoft tries to take this kind of direction.

    > Top level functions leads to a completly messy and almost unmanageable/understandable code.

    This is not to say that I consider all replies that disagree with my POV to be such. There were many reasonable replies with interesting arguments, including yours. My surprise was solely at a clearly knee-jerk, strictly emotional reaction some people here exhibited.

    When all is said and done, there are definitely other features way higher on the priority list for me (and, I’m fairly certain, the C# team as well), many of which have already been named. I’m just not a great believer in OOP for OOP’s sake.

  47. Anthony Tarlano says:

    +1 for doing..

    It is the one thing that I would most like to be more compatible with Python and F#!

  48. JM says:

    You know what I’d like to see? Easier integration of different languages in one project. .NET makes it technically possible to use (say) C# and F# in the same assembly through the use of modules (it’s all bytecode, after all), but Visual Studio offers no support for this scenario. If you want to do this, you have to create one project per language, divvy up all the dependencies and tie the assemblies together, which is usually too bothersome.

    Currently the framework is brimming with domain-specific languages which are implemented through designers, but I can’t mix in an *actual* language for a specific purpose if my project requires it. Why can’t I script the scripty parts with JScript.NET or use F# for the parts best expressed functionally and write the stuff I want component-based in C#? Then I wouldn’t need a "one size fits all" C# that’s chock full of things you selectively ignore (it isn’t there yet, but I agree with others that it’s moving in that direction with unsettling speed).

    Of course, using multiple languages in one project makes it harder to maintain, and requires developers with a broader skill set. But in this case the trade-off is obvious an up-front. If on the other hand you have a language that wants to be everything to everyone (C++, the PL/I of our times), then for any project it’s a crapshoot what approach it takes and what sort of developers will be proficient with it, and it also encourages idiosyncratic "geniuses" to reinvent everything at any given opportunity because the language lets them.

    I think people are deceived into overlooking the cost of multiple-paradigm development by extending single languages slowly — boiling frog and all that. There is a real need for it, but there’s a cost, and having one enormous language for your development obscures that. If you could mix multiple languages more readily, you both serve the need and make the costs clear.

  49. Gavin Greig says:

    Revisiting this topic and the comments after your new post, I’m particularly struck by JM’s comment which just precedes this one. I’d rather forgotten that it was possible to have a multi-language assembly, although at one point I was watching that development with considerable interest.

    In my opinion, if you really want to take a script-like approach for some items of functionality and a more obviously strongly-typed approach for others, then supporting different languages within a single Visual Studio project would be the way to do it. Requiring the use of a different language, in a different source file, with a different icon, etc., is a type of encapsulation that would make it easier to delineate the boundaries between one approach and the other. Better doing that than blurring the lines within a language.

    I take your point about considering all the possibilities, and recognise it’s a good thing; but of course you’re aware of the danger of diluting the things admire about C# for niche benefits. I hope the feedback you get from positing these things online is helpful; from outside Microsoft, the chance to comment is greatly appreciated.

    I also hope the feeedback here reflects the bigger picture, since it agrees with my opinions 😉

  50. Mark Sowul says:

    I was going to give a +1 for multilanguage assemblies, but think through what would be required for that in terms of dependency resolution.  Assume you have a class F written in F#, with dependencies on a class C written in C#, in turn with dependencies on class F.  With the language compilers being separate executables (hence each class would need to be compiled, incompletely, by a different program), think of what it would take to compile this.  If it takes compiler changes, now realize how limited your language interop scenario becomes.

  51. commongenius says:

    +1 for multi-language assemblies. THIS is where the future of interoperability lies.

    @Mark,

    The main scenarios for multi-language assemblies would not require circular dependencies, so leaving them out and calling it a limitation would not significantly reduce the usability of the feature.

  52. pminaev says:

    Regarding multi-language assemblies – getting basic VS support for this would be a good start. I had a Connect ticket opened for that:

    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=387155

    Note that this doesn’t talk about adding full-fledged VS support. You’d still have to muck with .proj files directly in this scenario (though once done, VS build would happily use that).

    However, for now, its resolution is rather disheartening – apparently, "the customer impact of doing this is fairly small" – which may well be the case, since I’m just one guy asking for a feature, and have no means of knowing how many more would find it useful. So – if you want it, go ahead and vote for it, send your usage scenarios, and so on.

  53. Denis says:

    Goodness, that’s some heated debate out there!

    Now, how about remembering one of the cornerstones of the modern society? Yes, I’m talking about TOLERANCE.

    Will you stop programming in C# if Microsoft takes the direction you don’t like? Will you stop driving if one more jerk cuts you off? Will you stop breathing if someone dares to pass winds in your presense? Be my guest!!!

    Now, Microsoft has money and resources to make BOTH sides of  the barricades happy: those who LOVE the top-level functions, and those who HATE them. WHAT IS WRONG WITH THAT??? What do you do whe you don’t like some kind of music? You don’t listen to it. What do you do when you don’t like some movie genre? You don’t watch it. So, if you don’t like some new language feature, DON’T USE IT. That’s all…

    Though I certainly appreciate the sentiment, I think you might be missing the point of the people who are opposed to this change. Yes, the argument “I find this feature distasteful” is countered by “so don’t use it“. But the more important argument is “I think this feature will lead many other people to write bad programs that are buggy, hard to read, hard to maintain, have high cost of ownership, and trade short-term relatively unimportant benefits for long-term pain and expense.”  This argument is not countered by “so don’t use it“, because the problem is the mess made by other people.

    We are well aware of this class of problems; I’ve blogged before about how we want C# to be a “pit of quality” language; that is a language where the constraints on the language naturally lead you to write well-factored, high-quality, robust, versionable, correct programs. A language where it is hard to write spaghetti code, memory leaks, or buffer overruns is, in our opinion, goodness. At the same time, we want to still support the features that lead to those negative outcomes, because arbitrary branching, deterministic finalization and direct access to memory are powerful and sometimes necessary. This is why we restrict the use of “goto” to never branch into a block. This is why we have the “using” statement. This is why we make you mark code that could overrun a buffer as being “unsafe”.

    The problem with designing a language where “a one-line program is one line” is that it makes it easy — maybe too easy — to write ten-thousand-line programs as though they were one-line programs. Whether the benefit of the former is worth the potential cost of the latter, and how to mitigate those costs while maintaining the benefits, are debatable points, and I welcome that debate.

    — Eric

    Although I have known quite a few people who strife to BAN the music or the movies they don’t like: they are all quite ingeniuos when it comes to finding pretexts: it’s violent, it’s sexually explicit, it’s this, it’s that… Can’t we, the IT crowd, who all have the IQ above average, rise above that sort of things?

  54. Denis says:

    Eric, thanks very much for your thoughtful comments.

    I am certainly not against a healthy debate about finding the proper balance between the language’s power and safety, although personally I tend to remember that good ol’ Ying-Yang symbol: both can grow or shrink, but neither can become larger than the other; a language can be either powerful, like C++ which, by the way, used to be my native language until my comparatively recent move to C#, or safe, like Java, where you cannot print anything without writing a native-code extension, but it can NEVER be both. If it’s powerful, then its power, like any other power (see any fantasy novel for reference), can be used for good or evil: to create elegant solutions or to introduce awful bugs; if it’s safe, it tends to put you under the glass and never let you out. The choice, then, is still yours: what do you value more, power or safety? Freedom or order?

    In politics, this is the most common argument against freedom of speech: what if someone, somewhere, some day will say something that someone else does not like, and then that someone else will grab a bomb, and..! :-) It’s also an agrument in favour of removing anything that can potentially cause any kind of controversy from the school program; as a result of that, I have met a few British nationals who had no idea who Rudyard Kipling was, and I also have to read Jack London’s Tales of Southern Seas from the Internet because some of his passages are now considered politically incorrect and so the whole thing has been removed from the print.

    But — back to the topic. A debate about the best choice between the power and safety of C#, or any language, is welcome so long as it does not become religious, or ideological: THAT was, basically, my point. Now and again, I see people become so passionate about the "principle" of something that, in their eyes, that priciple becomes more important than the thing itself; hence, threats to ditch C# altogether is it’s no longer "pure". And years before that, I knew some who used Borland C++ rather than Visual C simply because they hated, hated, HATED Microsoft (Grrr!!!) :-) By the way, even now Europe is  full of people who use Linux and curse Windows for the same very reason. How childish is that??? All those operating systems, programming languages, browsers, and the rest of it, are just TOOLS that serve some PURPOSE, and, in my opinion, getting so passionate about a tool that you forget its purpose is, to put it gently, immature.

    Cheers.

  55. commongenius says:

    @Denis,

    The decision between safety and power is not one or the other. Rather there is a continuum between them, the more power you have, the less safe you are (for the most part), and vice-versa, The trick of language design is to determine what level of safety you are willing to give up for what level of power. That is what the blog post and the comment debate is about, and I see nothing wrong with it. Nor do I think that the level of debate has come anywhere close to the point of invoking Godwin’s Law. Nor do I see what Rudyard Kipling of Jack London have to do with any of this.

  56. Denis says:

    @commongenius,

    It’s not the more power you HAVE the less safe you are; its’ more like, the more power you USE the less safe you are. That is, in essense, my point: if someone is not comfortable with a certain level of power, he is free NOT TO USE it; it does not mean that he SHOULD NEVER HAVE AN OPTION to use it, should he change his mind.

    I’m sure your car has something like 160 mph or 260 kph on its speedo; have you really gone that fast on a public road? Or should we now declare any car that POTENTIALLY CAN reach that speed dangerous and ban them all outright? It’s the same with a language: it does not FORCE you to use all its powers, and there are always "some others" who may find the powers we avoid (for the safety’s sake) extremely useful. So who is any one of us to decide for EVERYONE ELSE what’s right and what’s wrong for them? The more powerful the language is, the more of us are able to decide it FOR OURSELVES, and I see nothing wrong with that.

    As for Kipling and London, they are just examples of how the fear of controversy, manifesting itself in the so-called "political correctness", criples the culture: just because they occasionnally used some words, and rised some subjects, that someone, somewhere might find offensive, their works are disappearing from people’s memory. I would hate to see C#, or any other good and powerful language, cripled out of fear of its power.

  57. TheCPUWizard says:

    Denis,

    It seems YOU (and not commongenius) are the one missing the point.

    When dealing with a business development environment, is can be impossible to ENFORCE the useage of only "authorized" constructs. Code reviews do NOT ENSURE that they will not be used, only automated tools can hope accomplish this [and I have previously posted about the lengths some programmers will go to circumvent these, eve in the face of being fired].

    Once it is POSSIBLE to use something, you have to assume that it may be used. Then you have to start figuring out how to make sure it is used corredtly.

    I am NOT a ludite, and actually vote in favor of many of the features. I KNOW that the team at Microsoft (especially Eric) understands this COST.

    You statement  of "The more powerful the language is, the more of us are able to decide…" is the exact opposite of what heas been thre repeated experience of nearly every long term developer. The ONLY people who are truely qualified to make a decision (on any subject) are those who fully understand 100% of the alternativies and the risk/rewards of each. And the larger the required knowledge base is the smaller the percentage of people that will have the full knowledge.

    Your statement

  58. Denis says:

    @TheCPUWizard,

    As you yourself say, "the ONLY people who are truly qualified to make a decision (on any subject) are those who fully understand 100% of the alternatives and the risk/rewards of each."

    Now, the question is, WHO are those people? ARE there any such people, ever???

    As I move to software architecture and project management after slaving away as a developer workhorse for 19 years, I know how tempting it is to Command And Control: to Show Them All Who’s The Real Boss, to finally get your vindication. I also remember how much resentmen such methods inspire: THAT is the true reason behind the ridiculous "lengths some programmers will go to circumvent these [automated tools enforcing the coding standards], even in the face of being fired". So I say: yes, work with your team on the GUIDELINES for best coding practices, but understand that life CANNOT be totally formalised and there is ALWAYS a situation in which the law is meant to be broken.

    Like in a game of chess: as soon as you program your chess-playing application NEVER to place a knight in the corner, for example, it immediately runs into a situation in which such a move is the only chance to win (or not to loose).

    Also, more trust in your people will not hurt: they will not push the boundaries more than necessary, UNLESS YOU LIMIT THEM more that necessary. Think Scrum: empowered, self-organizing team. I’ve just got my CSM certification, so I still remember…

    And once again: NO ONE understands 100% of the ramification of each alternative, so it just might be convenient to keep them all handy, just in case the law we lay down proves to be wrong, and there is an urgent need for an alternative.