views:

1289

answers:

14

Here are my points to start with.

  1. I cannot guarantee that my structs are initialized with my default constructor.
  2. I cannot define a simple " == " operator overload on an interface.
  3. I cannot return const objects, which destroys encapsulation.
  4. I cannot define a simple generic Sum function because of operator + not working on generic type T.

Edit: Imagine you need to create a small type or maybe type hierarchy - double with accuracy and with different roundings. You would then understand why I need all these..

  1. I cannot decide where to place my instances: ref- or value-placement
  2. I don't have multiple inheritance which is the least pain (when you are not in one of those MarshalByRef situations...)!
+1  A: 

None of those things I see as issues at all, never really been a problem if you adopt the C# paradigm of programming, ie, don't program like a C++ programmer in C#.

The biggest pain is lack of real time / native code capability in C#

Keith Nicholas
@Keith Nicholas - I did some editing, so you can see why they are problems for me.
badbadboy
"The C# paradigm" does not include using operators? I disagree. C# allows you to overload operators, *except* you can't do it with interfaces because they chose to make operators static, and since interfaces define generic constraints, you can't do it with generic types either. That is just weak.
jalf
Operator overloading is evil[tm] anyways...
EricSchaefer
This is goofy. It seems to me the way you solve a problem should be problem-driven, not language-driven. And @EricSchaefer, from what adenoidal junior prof or blogger did you learn to use words like "evil" in C.S.?
Mike Dunlavey
+12  A: 

I hate how I'm hugely more productive in C# than I ever was in C++, because it proves I'm not a real programmer ;)

And I hate how C# doesn't have nearly enough string classes.

mackenir
I'm glad I'm not the only one who feels like that. ;)
Greg D
It's pointless now, but does that mean we would have been a lot more productive if we'd jumped on java?
le dorfier
I agree, I'm more productive in C# than C++, but that certainly doesn't make the language perfect. And as nice as C# is, that just makes its shortcomings stand out even more. You expect C++ to suck, so when you encounter areas where C++ is *better* than C#, it's just depressing. Hence this question.
jalf
IMO the productivity gains with C# are a result of simplification of the language to remove many of the problems with C++. One example: with C#, you actually get useful compile errors. Almost always with C++, because of the flexibility of the lang, compile errors are unhelpful and cryptic.
mackenir
Re: java. Makes me shudder to think ;). Actually, I've tried java a few times, and in practice, C# is just so much better to program in. It's strange, because superficially they are very similar. IMO C# is pulling away now, though, with subsequent versions. Also, interop is much smoother with C#.
mackenir
IMHO, the reason you're more productive with C# is the huge class library. If MS (or Mono) had released that as C++ classes, you'd have been a lot more productive in C++. That and the IDE. I don't think the C# language itself *really* matters.
gbjbaanb
I couldn't disagree more, @gbjbaanb.
mackenir
+2  A: 

You make some good points. A lot of what is "missing" was left out to keep the language simpler and avoid common pitfalls. Here are some thoughts on your items.

  1. Either: a) use a class or b) build a struct that doesn't need to be initialized using properties with lazy instantiation where needed. Search other SO questions to see why this was a good idea. As a quick example: private myStruct[100000000000000]; How long would that take to initialize?
  2. All objects inherit an Equals() method, but if you want to require a class to implement Equals, you might have your interface inherit from IEquatable<T>. You won't be using the == operator, but you can get the same behavior.
  3. Build immutable objects (i.e. objects with read-only properties). I agree this is limiting, because it's not always possible to make the objects within your objects immutable.
  4. Agreed. This would be very nice. Before releasing generics, MS at least added "where T : new()" so we could create a new instance of T. It would be nice if they added more of these. At least you can add methods to replace all these operators, which will make your code more friendly to other CLR languages anyway.
  5. Can you explain this one a little more?
  6. Interfaces are widely regarded as the answer to multiple inheritance. Granted, a standard mix-in framework would be nice as well. It doesn't sound like you miss multiple inheritance that much.
Neil Whitaker
#1 is rubbish. Yes, it'd take a long time to initialize, but if I create a default constructor on my struct *and* I create a huge array of the things, then it is because I want them to be initialized with my constructor regardless of the time it takes. Otherwise I hadn't done it.
jalf
jalf: that assumes you know this is the behavior of an array of structs. Structs would be the only case when creating an array calls constructors in a loop, so it would catch many people by surprise. After weighing the two sides, MS went with the principle of least surprise--a reasonable choice.
Neil Whitaker
@me.yahoo.com/neilwhitaker1: about #5,it goes together with #1. I don't want to use class, because it will be created on heap and always placed by reference, and structs are always by value and "in context/stack" If I could decide this per instance, like in C++, I could have created a class intead..
badbadboy
+12  A: 

The biggest thing for me is lack of RAII. Not having a guarantee that the destructor will be called in a timely manner to release resources is a big drawback for me. The using statement and the IDisposable interface is a poor substitute for a compile-time guarantee that no one is forgetting to release the resources.

Eclipse
Agreed. The using statement is nice, but it's on the wrong side of the fence. I want it on the type protecting the resource, not in the calling code.
jalf
Amen. Making exception-safe code with C is a royal pain. Still better than Java though.
Nemanja Trifunovic
@Josh - totally aggreed. I don't know much about this area but I believe you mean that there is no way to guarantee resource will be released like in C++ when the object is out of scope and destructor is called....
badbadboy
There is a cost to this: you'd need to double up a lot of syntax to distinguish between heap allocated and 'fake stack allocated' instances of objects. Of course C++ programmers would be used to this.
mackenir
@mackenir, not necessarily - a 'fakestack' object could be handled by the compiler - so all heap allocated objects would be zero-cost, 'fakestack' equivalents would have the (small) cost emitted as cleanup code at scope end - which you have when you use 'using' statements anyway.
gbjbaanb
+3  A: 

Well, here goes some downvote-bait...

C# isn't so bad, but what I really miss is the preprocessor.

I know the "powers that be" decided I didn't need it, and I'm sorry, but that really frosts.

Added:

Example of what I need to do sometimes. I have a DSL, which is the base language with some special statements layered on top, such as some special IF-type statements:

 #define IF(test){bool _test; if (IfUtil(Protect(_test=(test))){
#define ELIF(test) } if (IfUtil(Protect(!_test && (_test=(test))))){
#define ELSE } if (IfUtil(!_test)) {
#define ENDIF }}

So I can write

//
IF(some_test)
  ....
ELIF(another_test)
  ....
....
 ELSE
  ....
 ENDIF

And the boilerplate will be expanded for me.

Mike Dunlavey
The preprocessor was nice in some cases, but 99 times out of 100, it was used for horribleness.
Dave Markle
I know. That's sad. But I don't use it for horribleness. I raise the level of the language by using it as a code generator. It seems the C-sharpies want everyone to code like lemmings, and not do anything new or unusual, in my grumpy opinion.
Mike Dunlavey
... if they didn't think of it, it shouldn't be thought.
Mike Dunlavey
@Mike - why not use some other less-horrible mechanism for your code-generation needs? Wanting the preprocessor is like hankering for a stone axe when precision power tools are available. :)
mackenir
Although the one good thing about preprocessor is that it is integrated into the compile process. Perhaps this is what you like about it.
mackenir
@mackenir 1) because I guess horribleness is in the eye of the beholder, and it didn't stop MS from using it extensively, 2) I have no problem generating code by other means, but if the problem is simple enough the PP is really convenient.
Mike Dunlavey
@mackenir For example, I've got a pseudo-DSL that I use for dynamic UIs, http://sourceforge.net/projects/dyndlgdemo/ It has a souped-up IF statement that macros into an "if" statement plus some boilerplate. In C# I have to expand it by hand.
Mike Dunlavey
@mackenir Of course, I could write a parser for the DSL and generate C# from it, but since the syntax is 99% the same as the underlying language, that seems like a royal waste.
Mike Dunlavey
@mackenir Another thing I do that's "horrible", but saves gobs of code, is this: http://stackoverflow.com/questions/321143#321285.Maybe there's a better way in C#. I haven't seen it, but my mind is open.
Mike Dunlavey
The preprocessor is a powerful tool, but with more uses for evil than for good, and the good comes with bad side effects (like IntelliSense, Refactoring, and Debugging get harder).
Jay Bazuzi
@Jay: Somehow I got by for 50 years w/o IntelliSense and Refactoring. Debugging is a function of how many bugs you put in your code, and if it's generated, there are fewer of those. I reserve the word "evil" for genocide, AK-47, stuff like that. But thanks for your input.
Mike Dunlavey
Yeah, I got by without them too (a small fraction of your years). I think DRY is important, and we (the industry) needs to move to being able to generate code without blocking existing tools.
Jay Bazuzi
If you took half the time it took you to learn to generate, and actually generate, bugfree code with the PP and put that time into something like (e.g.) T4, I suspect you wouldn't miss the PP much at all, anymore. If C# had a PP, what makes you think it'd be close enough to C's for your stuff?
Greg D
I just added an example to the question. Now, rather than have a p***ing contest about whether T4 or PP is better, let me just point out that T4 is johny-come-lately, while I've been able to do this for decades.
Mike Dunlavey
I'm sorry if I'm a bit negative about the C PP. I've had to deal with broken macros that use the token concatenation operator to generate broken classes in bad, evil ways far too often in my career.
Greg D
I understand. It is a baby/bathwater situation. I have often wished for a PP debugger, so I could step through it and see where it was generating bad stuff.
Mike Dunlavey
+7  A: 

I shall quote an email I wrote to my colleagues recently titled, "My 'short' fuse with C#":

This is unbelievable! In C#, the following is a compile error:

short a = 5;
short b = 3;
short c = a - b;

Stating there is no implicit conversion from 'int' to 'short'. It seems that there is no minus operator defined for shorts, so a and b get implicitly cast to an int to do the arithmetic, resulting in an integer return value! The way to get it compiling (probably still with the conversions to/from ints) is like this:

short c = (short)(a - b);

What a dog of a language.

As an experienced developer across a number of platforms and languages (predominantly C/C++ though), I am constantly suprised by the holes C#. Not being able to do arithmatic with shorts is just crazy.

All these holes just lowers my confidence in C# and .NET and makes it feel like a toy.

Oh, and if I had mixins or macros (preferably mixins), then I might not feel like I need multiple inheritance.

Cheers,

Dan

Daniel Paull
I don't think that particular example is a big deal, but I agree, it often seems as if there are areas in C# that "they just hadn't thought of". A shame, because the parts they *have* thought of are generally very nicely implemented.
jalf
Wow. I didn't believe it until I pulled out a compiler and saw for myself. There'd better be a reeeeeeeeeeeally, reeeeally good reason for this. (I can't for the life of me think of one!)
Dave Markle
lol i wouldn't have expected that to fail in any language -.-
Johannes Schaub - litb
That's not a bug, it's the designed behavior of C#. The result of a - b could be to large (in absolute) value to fit in a short. i.e. -60000 - 60000 = -120,000, which is too large for a short. Also think about this: int c = a - b. You would be really confused if a - b was truncated to a short.
So does C# convert ints to longs to avoid overflow in arithmatic? I think not, but I'll check with the compiler...int a = 5;int b = 6;int c = a - b;egad - it compiles!!It's an oversite in the language, no bones about it.
Daniel Paull
In .Net, short aka Int16 is only intended to be used for interop and special cases.
Christoph Rüegg
So is that a reason not to include arithmetic ops? No way man. I guess that since the Int16 "is only intended to be used for interop and special cases" there wouldn't, say, be an overload of Math.Abs() for Int16. No wait, there is! It's a damn integer type - it should have arethmetic ops.
Daniel Paull
The MSDN (http://msdn.microsoft.com/en-us/library/wch5w409(VS.80).aspx) claims that "Binary - operators are predefined for all numeric and enumeration types to subtract the second operand from the first." So, the doco is wrong... or the language is wrong. Heck, there aint even a unary - on Int16.
Daniel Paull
See http://stackoverflow.com/questions/129023/net-integer-vs-int16 for more details about it (and why).
Christoph Rüegg
ummm... that thread does not mention missing arithmetic ops on Int16. If it's bad form or inefficient, then make it a compiler warning if you must, but a compile error?? The language is broken.
Daniel Paull
Ok, I've looked up the C# spec, and the behaviour is as per the spec. Section 4.1.5 (Integral types) in the csharp 1.2 spec for those playing at home. So, it's the language spec that's broken! I wonder what happens if I add two shorts in C++/CLI...
Daniel Paull
strangely one of the "why c++ sucks" bits commonly quoted is roughly the exact same quote (only they tend to use operator+ for their example of poor casting of results). :)
gbjbaanb
+1  A: 

Garbage Disposal

+2  A: 

I also miss basic stability and simplicity. To me it's just not a benefit that new features keep being added to something I already can use quite effectively, thank you. A prime example is "var".

le dorfier
Hold onto your hat, because they're adding 'var' to C++. They're calling it auto, to confuse you. In fact, C++ is crying out for it.
mackenir
Also, C++ is going to be catching up further with C# when lambdas are added.
mackenir
+17  A: 

I spent two years programming with C# and then took the first opportunity to jump back to C++. Some of the things I dislike about C#:

  • Lack of free functions and perverse workarounds like static classes.
  • Too much casting. There are too many .NET framework methods that return object and than you need to cast down. Before generics it was even worse.
  • Memory footprint. It is bloody impossible to keep memory under control with C#
  • Verbosity. Somewhat addressed by type inference, although the choice of the keyword is unfortunate.

In general, C# is targeted to in-house business programming and it is probably good for that purpose, but that is not what I want to do. For all interesting stuff: system programming, graphics, games, real-time and embedded systems, etc, C++ is a much better choice.

Nemanja Trifunovic
Compare foreach to the standard STL iteration pattern and I think C++ loses out on the verbosity argument. Swings and roundabouts.
mackenir
foreach in C#:foreach (int i in fibarray)foreach in c++[boost library]BOOST_FOREACH( char ch, hello )sure, either loses out on the verbosity.
Comptrol
+5  A: 

C# lack of const-correctness is a shortfall. I really wish C# had #include

Roger Nelson
There's not much to gain with #include, and a lot to lose.
Jay Bazuzi
+2  A: 
  1. It is way too easy to inadvertedly alias objects and then be surprised by how a change to a property somewhere can cause all sorts of bad effect.
  2. Pointers to members. Way too many libraries (e.g. Workflow Foundation) use strings and reflection to compensate for the lack of them.
erikkallen
+1  A: 

In C# 2.0 I became disappointed in closures feature - way too much boilerplate and weird syntax limitations.

The Adobe Flex ActionScript3 language is a statically typed language (has compile-time type checking) and very much resembles Java or C#. Unlike Java, but like C#, it also has properties and events (plus very nice data-binding features built on that foundation).

Yet due to its JavaScript heritage, AS3 retains a closure feature. This works very well in AS3 coding. Coding in AS3 has been more pleasing that either Java or C# 2.0. AS3 seems simpler, cleaner, and yet sufficiently powerful.

Does lambda expressions address this closures clunkiness in C# 3.0?

(And BTW, previous comments have suggested that C# is only good for internal business software. Yet lots of public Internet facing Adobe Flex software is out in the wild. Plenty more public facing Flex software is in development. I say this to point out that a managed code runtime can indeed be used for public facing software if the runtime is suitably designed., as Flash/Flex runtime has been for the web.)

RogerV
+7  A: 

C# drawbacks compared to C++:

  • There is no support for const-correctness. I find this sad, because 80% of all parameters passed to functions are constant (in functional programming this is even 100%). It is very nice if you can add compiler-checked documentation to your code stating which parameters will not be tampered with.
  • There is no support for non-null pointers (cf. C++'s "references"). This is a shame, because 95% of all parameters passed to functions are non-null pointers. In C++, you can add compiler-checked documentation indicating which pointers are ensured to point to something. In C# you have to wait until runtime to get this feedback.

However, C# also has some advantages over C++:

  • There is much better support for working with components (assemblies), which is a big advantage. In C++ this is a real pain, for third party libraries as well as in-house components.
  • C# has a large standard library, which is a big plus. C++ especially lacks a good standard user interface library.
  • The namespace system is better. C++ has the problem that "using namespace" doesn't work in header files, which more or less ruins the feature. I don't understand why they don't fix this in C++ (I know, I know: the eternal backward compatibility issue which paralyzes progress).
  • Extension methods are a great feature, which I really mis in C++.
  • Compiling code at runtime. This provides for an out-of-the-box plugin system.
  • The reflection feature sometimes proves useful.

All in all, I still prefer C++, as I think the two features I listed are major ones. C++ was there first, so a new programming language should be much better to justify its existence.

Dimitri C.
Very good points here. Vote this up.
Neil Whitaker
+3  A: 

A good list of problems with C# can be found here.

Dimitri C.