tags:

views:

1901

answers:

22

Asking the same of Java yielded some very interesting responses, so I thought it would be only fair to ask the same thing of C#, probably Java's closest rival.

I actually like this sort of question because it's a lot less subjective than "why should I choose this language" or "why is this language so great."

So.. what's wrong with C#?

A: 

Nothing... I think it's Perfect!

GateKiller
Yes, that's true: "nothing is perfect"
OscarRyz
+18  A: 

To a lesser degree, C# has the same problem as Java, namely its verbosity (code bloat!). Although most features of newer versions explicitly address this weakness.

The most obvious weakness is perhaps its dependency on the .NET platform which still makes it kinda limited to Windows, although Mono is beginning to pull it over to Linux and OS X.

Compared to VB, I find it a weakness as well as a strength that there are two virtually equivalent languages. On the one hand this is great because it gives us more choice, on the other hand this means that within Microsoft there are two competing teams that often don't communicate well enough with one another and basically spend twice the resources that one team alone would consume.

From a language designer's point of view I find the choice of syntax poor because the only reason for it was habit and marketing strategies and not technical reasons.

There are a lot more minor weaknesses but all in all I think it can be concluded that C# is one of the better tools currently on the market, especially in combination with the surrounding ecosystem.

Konrad Rudolph
Actually, with the new features (closures, lambdas, linq, anonymous types, property initializers, and default parameters) it's not as bloated as some (C and C++ come to mind).
Filip
Of course, compared to C *nothing* is bloated. Sorry, but that's just like saying “it’s not as wet as the ocean”.
Konrad Rudolph
@Konrad: C is bloated? The language itself, not "just" the programs written using it, that need to implement complicated features, and thus require a lot of code?
unwind
@unwind: C makes you write bloated code. The degree of syntactic clutter and boilerplate code required even for relatively simple problems is completely unmatched by any other language still in use.
Konrad Rudolph
@Konrad, Assembler is far more bloated and will probably remain in use longer than C. I agree with your main point though.
Pete
+2  A: 

What's wrong with c# is it is from Microsoft. IMHO It's a very good language, but people just love bashing MS, it would get much better rep if it wasn't from microsoft.

paan
Not sure why this was downvoted, because there is some truth in it. When many people hear "Microsoft", they think of the Microsoft that (rightfully!) got kicked in the balls by the Anti-Trust thing. But especially on the .net team, it's IMHO a better Microsoft now - still, perception could be better
Michael Stum
Agreed there is truth in this. Downvoters should leave a reason!
Si
+1  A: 

I don't think that C# 3.0 gives you much to complain about, unless you dislike static typing and/or case sensitivity, but that's just a matter of personal taste, and even in the case of static typing, you have type inference to ease a lot of the pain. Recent additions to the language, such as LINQ, lambdas and so on, fill in a lot of gaps.

There are only a couple of things that niggle me about C# a bit. One is the fact that it is a compiled language. This means that the edit-compile-test loop can be a bit slow at times, especially when you are doing ASP.NET development and it can take up to a minute between making a change and seeing the effects of it in your browser. However, even then it's a trade-off -- you get a boost in speed, and a lot of syntax errors are trapped at compile time that might well slip through the net in an interpreted scripting language.

The other minor niggle is that it can be a bit over-strict in some cases. Covariance is an example -- you can't do this for instance:

List<object> myList = new List<string>();
jammycakes
Re: the list assignment. You will never be able to do that, nor should you be able to. myList.Add(5) would compile but would attempt to add a boxed integer to a list of strings.
Daniel Earwicker
+8  A: 

I would say the following:

  1. It's statically typed. I'm not trolling, just stating fact. There are things you just cannot do easily in C# that you can in other more dynamic languages. There are workarounds (the reflection facilities in .NET along with the code generation facilities) but it definitely is an issue with which you need to make peace before you plump for C#.
  2. Your choice of platform is limited. Yes, there is Mono, but the "golden path" for C# development is definitely Visual Studio + Windows. Having said that, I haven't tried SharpDevelop yet - and people do have success using things like Emacs. But a lot of the development niceties of the .NET platform come with Visual Studio.
  3. There are some niceties in Visual Basic that don't exist in C#. The one I'm thinking about in particular is XLinq support. XML literals in Visual Basic 9.0 are superb, and C# just doesn't have them. Having said that, there is nothing stopping you from splitting out your XML heavy classes into a separate assembly and using VB there.
Simon
I love the compiler checking my types instead of finding out at runtime that my logic is wrong.
Ed Swangren
"It's statically typed": I'd consider this a *huge advantage*, as it helps the compiler to find bugs for you.
Dimitri C.
+13  A: 

.NET framework dependency

Don't get me wrong, I love .NET framework but sometimes I do non-GUI C# applications that could run also on Linux servers. Yes I could use Mono but that would mean give up C# 3.0 (expression trees, LINQ to objects, lambda expressions).


Verbose syntax

  • Lambda expressions without parameters still require to write ( ) =>
  • var keyword in my opinion completely useless
  • actually now when I'm thinking about it, many other keywords are useless and compiler could understand meaning of the code without them just as well
  • type inference could be better, for example value returned by method can be figured out by compiler (or intellisense) without explicit declaration.


Forced memory-management

This is not as much problem of C# because it applies to whole .NET framework, but I would prefer to implement in some of my projects my own garbage collector or free the memory manually just like in C++. GC does things right most of the time but from time to time you deal with specific cases where you need more control than usually.


Annoyances

Some apply to the whole framework, not just C#

  • Missing non-nullable reference types. string would be a perfect fit and many others. I see no reason why compiler couldn't have this feature.
  • in progress :-)
lubos hasko
The Mono C# compiler is considered feature complete for C# 1.0, C# 2.0 and C# 3.0 (ECMA) : http://www.mono-project.com/CSharp_Compiler. You can do all LINQ stuff in your Linux Box
Daok
how can you not like "var" ?Which one is shorter?IList<IList<string>> stuff = new List<IList<string>>();var stuff = new List<IList<string>>();
Filip
@Filip, what about just "stuff = new List<IList<string>>();"?
lubos hasko
Var keyword can be a great time saver as long as it's used responsibly!
xan
@lubos hasko, what if somewhere you put stufff = null. Did you misspell the 'stuff' by adding an extra 'f'? If the compiler reacts to any such assignment to a new name as implying a declaration of a new variable, it can't help you by catching mistakes like this.
Daniel Earwicker
String works great as an immutable reference type. It means that strings aren't copied unless they are modified. If they were value types, they'd be copied all the time. What you really want is the ability to declare a reference-type variable as non-nullable, which would be a great feature.
Daniel Earwicker
@Earwicker, I think if you misspell a local variable, you don't really need compiler to tell you. scope is too small (single method) and you will always find out once you test your method. I don't have any hard data but this is where static typing languages feel kind of verbose.
lubos hasko
var is necessary for declaring anonymous objects. its not just in there only to save time
Shawn Simon
Your second and third points under verbose syntax seem contradictory... "var" is the compiler's way of saving you a lot of keystrokes and potential errors, and personally I think making new variables without any type declaration would be a really bad idea because it could lead to ambiguities and unintentional, difficult-to-find bugs.
Asmor
@Asmor, I don't agree with that. I mean what you say makes sense in theory but practically most dynamic languages don't have any keyword for variable declaration and yet this is not the problem.
lubos hasko
@lubos hasko: the languages you're talking about are mostly weakly typed scripting languages, not statically typed languages. You *have* to declare the type of a variable, even implicitly (which is what var does)
Thomas Levesque
You can do your own memory management in C#, if you want to. The System.Interop namespace has the tools for this sort of thing.
John Fisher
A: 

I concurr with the static typing being a bit of a drawback, though its not insurmountable. Also, its lack of optional parameters. Between those two doing things like automating office is a nightmare

Conrad
+7  A: 

A bit off topic, but anyway...

...you can't do this for instance:

List<object> myList = new List<string>();

No, because that doesn't make sense. That way you could add objects that aren't strings into the List<string>, like so:

List<string> strList = new List<string>();
List<object> objList = strList; // Both variables point to the same list
objList.Add(new object()); // Now you add a object into the strList

Update:

I just saw a talk by Anders Hejlsberg on the future of C#, where he says C# 4.0 will add safe co- and contra-variance. That is, in C# 4.0 you will be able to do this:

List<string> strList = new List<string>();
IEnumerable<object> objList = strList;
foreach (var o in objList) Console.WriteLine(o.ToString());

For more information on C# 4.0, see the talk or MSDN.

Tom Lokhorst
A: 

Konrad writes:

Compared to VB, I find it a weakness as well as a strength that there are two virtually equivalent languages. On the one hand this is great because it gives us more choice, on the other hand this means that within Microsoft there are two competing teams that often don't communicate well enough with one another and basically spend twice the resources that one team alone would consume.

Sorry, but I'm kind of getting tired of this Microsoft "criticism". VB and C# do have plenty of similarities... but plenty of differences too. Why should you care if they're "wasting resources" (your opinion)?

If C# and VB were implemented exactly as-is by two separate open source projects, everyone would be falling all over themselves praising their work. But let MS actually deliver choice on their own (bastards!) and they're just "dumb old MS". Sorry, this is boring.

On the other hand, if MS had never created, say, VB.NET and "only" offered C#, just watch the me-too crowd coming out of the woodwork complaining about MS not offering enough choice. Bah.

Microsoft deserves plenty of criticism... but the whining about "too many ways to do something" (smart clients, data access, MVC vs. WebForms, C# vs. VB.NET, etc. etc. etc. etc.) is getting absurd.

JoshL
+1  A: 

Before starting, let me express my surprise that the weakest and least interesting argument in my debate was so heavily attacked.

VB and C# do have plenty of similarities... but plenty of differences too. Why should you care if they're "wasting resources" (your opinion)?

It's the waste of intellectual resources that bothers me. I believe it was Stepanov who once said that when you learn a new language it should change your perception of concepts. If it doesn't, it's worthless. Since VB and C# are so similar, it's difficult to find C# concepts that aren't also in VB.

Furthermore, the two teams don't collaborate well enough. There's plenty of evidence for this. Paul Vick, chief VB developer recently wrote about introducing iterator methods into VB (the yield return feature from C#). He writes that the feature will probably not appear in the next version because it's a lot of work to do. What the hell? Why can't they copy the C# implementation from the people next door?

(Actually, it's a little more complicated because the planned VB feature is much more powerful than the current C# implementation but the argument remains the same.)

But let MS actually deliver choice on their own (bastards!) and they're just "dumb old MS". Sorry, this is boring.

That's not what I wrote, nor was it implied in any way. I even said that on the one hand it's great to have the choice.

On the other hand, if MS had never created, say, VB.NET and "only" offered C#, just watch the me-too crowd coming out of the woodwork complaining about MS not offering enough choice.

Obviously, it should have been “only VB” ;-) Offering C# was just a clever marketing trick to get the C and Java folks to bind themselves to the Microsoft platform. (And please don't take this too seriously!)

Konrad Rudolph
A: 

I've written about this a few times before: Why I like VB.Net VB.Net vs C#, Round 2

Joel Coehoorn
+1  A: 

@lubos hasko

Don't get me wrong, I love .NET framework but sometimes I do non-GUI C# applications that could run also on Linux servers. Yes I could use Mono but that would mean give up C# 3.0 (expression trees, objects to LINQ, lambda expressions).

Check out the Mono 2.0 Preview Release, which implements everything you mentioned. It even supports Linq to XML in C#. It is scheduled to be released at the end of september.

Adam Lassek
+3  A: 
mmattax
uh...why would you pass a reference if you don't want to modify it?
Steven A. Lowe
@Steven A. Lowe - I realise I'm rather late to the party, but in C++ although you clearly wouldn't do this for an `int`, you might for a class where copying has been user-defined as a costly operation. The recipient only needs readonly access, hence they can safely access the original instance, hence passing a const ref makes perfect sense.
Daniel Earwicker
@Daniel Earwicker, even better would be a compiler that realizes your `const` variable is expensive to copy and passes it as a reference automatically.
Brendan Long
@Brendan Long - in theory the CLR's JIT compiler could do that without help from the C# compiler. It already does inlining, which eliminates a lot of copying. Of course they may never do this because in practise the performance benefit may be unmeasurable for most real programs. Some other interesting things here: http://blogs.msdn.com/b/clrcodegeneration/archive/2007/11/02/how-are-value-types-implemented-in-the-32-bit-clr-what-has-been-done-to-improve-their-performance.aspx
Daniel Earwicker
+2  A: 

If your going to put code by reference functionality into the language, why wouldn't you allow constant references?

Because it's complete nonsense. const& in C++ is an optimization that is used to prevent the compiler from making an unnecessary copy, nothing more. In C#, this is redundant as no copy is made during a method call at all for reference types. Furthermore, value types should be small enough to not benefit from pass by reference. ref passing in C# has the sole purpose of modifying the argument within the method and const would prevent this, thus negating the effect.

Konrad Rudolph
Dimitri C.
@Dimitri: Yes I know that but that’s irrelevant in the context of C#. If you want to prevent a variable from being modified in C#, don’t pass it in by reference – it’s as simple as that. Pass by ref in C++ and C# serve fundamentally different purposes: in C++ it’s a performance tweak, while in C# it’s an expression of intent: “I will be modified”. Passing a const ref in C# would therefore amount to saying: “I will be modified, but I cannot be modified” – which is pure nonsense.
Konrad Rudolph
@Dimitri: if you want to prevent the modification of the *whole* object (rather than just its reference) const correctness is indeed a very useful concept in C++. To achieve a similar effect you need to use immutable objects in C#. However, this has got nothing to do with passing const references to a method in C#.
Konrad Rudolph
@Dimitry (By the way, I don’t dispute the usefulness of const correctness and I agree that it might have been nice in C#.)
Konrad Rudolph
Dimitri C.
+3  A: 

I actually find the syntactic similarity between VB.NET and C# to be refreshing.

It doesn't seem useful on the surface, but imagine two very different developers with very different histories:

Developer (A) has been working with informal training all of her life, mostly in VB6 due to its simpler learning curve and forgiving style. The style of C-based languages seems cryptic and even daunting to her.

Developer (B) has been rigorously brought up in C-style languages. She is at home with the style, and comfortable with both the benefits and limitations of this class of languages. She would consider the extra verbosity of VB to be a waste of her time.

However, since C# and VB.NET now share pretty much the same feature base (they share common syntax/Domain Language [if you consider "programming terms" as a domain]), and the style that is used to perform most tasks is now very similar between the two. Developer (A) can get her feet wet in a C-like environment while still working in relatively familiar territory. Developer (B) can continue to work in C# and trust that, gradually, Developer (A) will become less and less intimidated by her code as Developer (A) begins to realize the truly deep similarities between VB.NET (which Dev A is familiar with) and C# (which Dev A is now able to be exposed to in a more "get your feet wet" manner).

Yes, some will say Developer A should just jump in... but in the real world, I would venture to say that there's more of Developer A out there than Developer B. Having two very similar languages that come from very different backgrounds presents the opportunity for a merger of worlds: and maybe even an opportunity to help bring Developer A closer to the skills of Developer B as A begins to understand more of what B writes.

EdgarVerona
+4  A: 

I've just thought of a real criticism. Not so much of the language itself but more of its creators.

The C# team has released some pretty polarizing coding guidelines (e.g. “never use var declarations except for the result of LINQ queries”). Unfortunately, most of these opinions are not justified in the least. It's hard to decide if there simply is no technical rationale behind the decisions or whether this rationale is nontrivial. If it is nontrivial, please provide it! It's important. And if it's subjective, tell us so. As it is, I ignore most .NET programming guidelines created by Microsoft because they're worse than useless in their current form.

To take up the above example, the C# team gives us a great feature to fight code bloat and then immediately takes it away from us. Surely there must be a better reason than arguable readability loss?

Konrad Rudolph
Heh. I almost always declare locals with the keyword var. But I'm a bit of a functional programmer: I like universal type inference.
Justice
Universal type inference...Very funny :)
Joan Venge
That rule makes sense to me. var often makes the code harder to read as the reader will often need the signature of the method calls. You now have to do a lot more tracing and count on the IDE in places where the code would have been self explanatory. The only place var is really needed is with anonymous types.
kervin
@kervin, you’ll find that many/most people (at least on Stack Overflow) disagree with your view – in fact, usage of `var` has been the topic of a few discussions. In a nutshell: the claim that `var` makes code harder to read is just that: a claim. *I* claim that the opposite is often true, since it helps to remove useless redundancy. There is no “more tracing” involved, and code is not made less self explanatory through its use. The user will not, as a general rule, need to know the signatures of method calls any more than without `var`.
Konrad Rudolph
Resharper makes a very reasonable choice - it suggests you use `var` if the target type is already stated in the initializer, e.g. the insane classic: `StringBuilder stringBuilder = new StringBuilder();` Who could honestly argue with `var` in that kind of situation? Ditto `MyClass myClass = (MyClass)obj;` Personally I use `var` wherever possible. It is particularly important for the loop variable of `foreach`, to suppress the implicit cast that is unfortunately inserted if you specify a type for the loop variable.
Daniel Earwicker
+1  A: 
mmattax
I'm nearly two years late here, but... arrays are reference types. I think you have a point but not in quite the way you've explained it - as Konrad says, const on ref/out parameters would be pretty useless in C#. But better support for immutable reference types is long overdue, and would be applicable to all reference types: classes and interfaces. Also to lambdas. It's becoming more and more necessary to be certain that specific things will not be modified by an operation. This will hopefully be a big theme in C# 5.
Daniel Earwicker
+1  A: 

@mmattax:

it is used as a guarantee that a method can not alter the reference, it is not just a compiler optimization.

Right. I implied that in my posting, because if the programmer doesn't want the value modified, she can simply pass by value instead of by const-ref. The only reason to pass by const-ref instead of by value is to prevent an unnecessary copy.

I understand for reference types, but what about non-reference types, things such as arrays?

Arrays are actually reference types.

The coding guidelines for .NET programming tell you that only very small types should be value types and for very small types, passing by reference is not cheaper than passing by value. ref should never (!) be used for optimization but only if the value has to be modified.

Konrad Rudolph
A: 

i loathe sealed classes. it's OOP for cryin' out loud, let me inherit!

Steven A. Lowe
You really want to design every class for inheritance as well as usage? Inheritance is about the strongest class dependency there is: there are few really well designed and change resistant class hierarchies out there. (As opposed to using inheritance to hack classes in ways the author never thought about: that's cool, occasionally useful, and almost always unmaintainable in the long run.)You never want the compiler to optimize out virtual calls? You might as well complain about LISP having integers: "it's a functional language, let me use Church numerals instead!".
Pontus Gagge
@[Pontus Gagge]: that made no sense. And the LISP analogy is ridiculous. But thanks for sharing.
Steven A. Lowe
+4  A: 

There are lots of things I'd like to add or fix in C# and which I think would be easy to add/fix. I think that's a different question though.

As for things that seem to be permanently wrong, or at least would be very hard for MS to fix now, there aren't many. Let's see...

Loop Variables and Lambdas - The loop variable in foreach should be captured as a copied value by anon-funcs/lambdas inside the loop statement/block. Instead it is treated as if it was declared outside the loop, which is not what you want in 99% of situations, leading to the well-known lambda-foreach bug as documented on a thousand blogs.

No Free Functions - It should be possible to declare a function in a namespace (called a free function in C++). Instead we are required to declare them as static class members. In practice this means that we are forced to put a . in the middle of our free function names. This is required by the CLS, but I think it's a rather outdated idea.

struct - I originally thought this was a superb improvement over Java, user-definable compound value types, because as a C++ user I was prejudiced against the idea of having to allocate everything from the GC heap. But in practice they are terrible things with inconsistent and surprising behaviour, and the GC heap performs brilliantly anyway. Structs would have been better if they were required to be immutable. Also there should be a way to make the default constructor private so that the compiler will stop you from using the struct in any context where the default constructor might be called, e.g. in an array.

void - if I have a function void Foo() why can't I say return Foo()? Should be fine from another void function. If this were so, we wouldn't need Action, just Func<void>. As we find more uses for functional style, the more we will encounter these situations where we have to write the same generic type twice with different names, to deal with this unnecessary asymmetry in the type system.

I also think when dynamic is added in version 4, that will be a largely unnecessary blot on an otherwise very carefully defined and evolved language. Maybe I'll feel differently when I try to use it, but I seriously doubt it.

Daniel Earwicker
Lambda foreach bug?
Chris Marisic
@Chris - http://blogs.msdn.com/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx
Daniel Earwicker
That's right I remember seeing this at some point, also I'm glad I'm immune to this potentially very weird bug as resharper is smart enough to see this and can fix it by copying the value to a variable for you.
Chris Marisic
+1, For value classes, I find Scala's `case class` approach much better than C#'s `struct`.
missingfaktor
+1  A: 
  1. With the "no fall through in case", it is very hard to unroll loops (a la Duff's Device).
  2. No RAII. "using" is a poor substitute.
  3. Required spelling out of enums in case statements
plinth
Well, manual loop unrolling has no place in such a high-level language anyway. It can only go wrong. Rather, rely on the capability of the just-in-time compiler. True pooint about RAII though.
Konrad Rudolph
C# certainly supports fall-through, read http://msdn.microsoft.com/en-us/library/06tc147t%28VS.71%29.aspx
Dour High Arch
I think it should support fall through without goto statements, if they're worried about programmer error make it take a keyword like continue to nobreak!
Chris Marisic
+8  A: 

It's becoming less and less simple to use. It seems like there's never a feature in another language that Microsoft doesn't feel it must add. So you end up with multiple ways to do the same thing.

le dorfier
I actually love that very much.
Developer Art
This is fine for me, but I often wonder how they can keep the compiler from becoming too big to maintain, not only for Microsoft, but especially for the Mono project.
Dimitri C.
Considering C# in the light of the previous generation, we have VB.NET for the old VBers. C# is just what the old C++/Java folks relate to (and it keeps expanding in the same fashion.) But nothing is left for those of us who sometimes at least prefer the minimalist C model. A true class-based C language would be nice - equivalent to a successor to C++ if it had been done properly.
le dorfier