tags:

views:

688

answers:

13

What are the most common or vicious mistakes when experienced C++ programmers develop in C#?

+17  A: 
  • the difference between struct and class in the two
  • the difference between a using alias and a typedef
  • when do my objects get collected? how do I destroy them now?
  • how big is an int? (it is actually defined in C#)
  • where's my linker? (actually, Mono does have a full AOT linker for some scenarios)
Marc Gravell
How big is an int. The joys of a well defined language and environment :)
Spence
I feel obligated to point out that C++ leaves it implementation defined so that the compiler can use the most performant native type rather than being restricted by the specification. There are sized types available if you need that.
Mark B
@Mark In C99 there is `stdint.h`. This is _not_ in standard C++ yet. (It is in tr1, but not implemented in MSVC 2008) See the wiki entry on stdint.h
KitsuneYMG
+5  A: 

Calling GC.Collect.

Petoj
+1. I have seen code where the programmer was so worried that his objects would stay in memory he called it continuously.
Yacoby
+3  A: 
  • RAII vs IDispose
  • value type vs ref type (struct vs class, boxing and unboxing, etc.)
Findekano
+10  A: 

I've seen many C++ coders code in a COM style in C#, trying to deal with the inadequacies of the language. C# provides lots of a type safe support for your enums and there are usually nicer APIs then P/Invoking back down to C++.

The other thing I've seen catch most people out is that C# generics are not templates.

Spence
+1 for templates vs generics - good catch.
Marc Gravell
+1  A: 

Attempting to implement const correctness on strings.

Bill
+3  A: 

Thinking that "garbage collection" = "I never have to worry about object lifetime at all". For instance, opening a FileStream and forgetting to close it.

Or:

  1. Allocating a lot of objects
  2. Putting them in a big global dictionary (usually after "I know, I'll make a cache")
  3. Wondering why the application's memory usage always goes up and never down ("but it's supposed to garbage collect!")
Tim Robinson
Doesn't `FileStream` close in its destructor like `fstream`?
henle
@henle: You don't know when the destructor will be called, so it's better to call dispose, manually or via using semantics.
Brian
Good point. I guess that applies to c++ as well.
henle
Well, in C++, you are sure that the destructor will be called as soon as the variable gets out of scope, so there is usually no need to explicitely dispose ressources (this is the point of RAII).
Luc Touraille
The `FileStream` finalizer gets called when the CLR needs to reclaim memory. If there's plenty memory free, then the `FileStream` may not get finalized until the program exits.
Tim Robinson
Are you kidding me? Destructors aren't called when they should? Isn't that a major problem?
henle
.NET finalizers aren't the same as C++ destructors. If the cleanup code isn't critical then you can leave it to garbage collection time (finalization). If you do need deterministic cleanup -- like closing a file handle -- call `IDisposable.Dispose`.
Tim Robinson
+3  A: 

Confusing "pass by reference" and "reference type":

void GetAnArray(int input, ref string[] output);

(Compare with C++: void getAnArray(int input, std::vector<std::string>& output);)

Tim Robinson
+2  A: 

Writing the full namespace each time.

This is fine in C++ when you're typing std::this or boost::that. Not so great in C# when you repeat System.Windows.Forms.Whatever all over the place.

Tim Robinson
A: 

using Hungarian Notation and other C++ naming conventions

private int m_iMyIntField;
class CWidget { ... }
Nathan Ridley
Misused Hungarian Notation isn't particular to C++, and it's more an artifact of the WIN32 and MFC libraries.
Binary Worrier
+3  A: 

Forgetting to specify access modifiers for every class member.

Gorpik
Not entirely necessary.
Judah Himango
@Judah Himango: What I mean is that in C++ you use labels for the different access zones. It's happened to me a lot that I forgot to write `public` before a method, because the previous methods were also public. And I see this happen all the time to C++ programmers learning C#.
Gorpik
Ah, now I understand what you mean, thanks.
Judah Himango
+3  A: 
  1. Using structs in favour for classes all the time.
  2. Using in, out and ref parameters all the time (This is a result of point 1).
  3. Using int values as error conditions instead of using exceptions
  4. Using the virtual keyword instead of override keyword.
  5. Thinking that char is an 8 bit signed value.
codymanix
The first three sound more like mistakes C programmers would make... or maybe very poor C++ programmers.
Tyler McHenry
C++ programmers, like C programmers are used to think that using value types most times is fine.
codymanix
#3 is equally wrong in C++ and C#; it looks more like something a C programmer would do in any of those languages.
Gorpik
Re #3: "Return codes considered harmful"? I'm sorry, but if you need to collect intermediate results and need to keep going exceptions are a no-no. Enum return codes have their place. Having try catches to control the "regular" flow is not the greatest idea.
argatxa
+3  A: 

Incidentally, the C# compiler has a number of heuristics in it for helping out the experienced C++ programmer who is a novice C# programmer. For example, if you say

int x[];

the compiler will helpfully point out that the [] is a part of the type in C#, so you probably meant

int[] x;

C# also allows things like putting unnecessary semicolons at the end of a class declaration so that C++ programmers who are in that habit don't get bitten by it.

Eric Lippert
+1  A: 

One that got me, and I believe a lot of non C++ people too, was leaking memory due to registered events keeping an object alive.

IDisposable grated to begin with (and still does if I'm honest) but was pretty obviously going to be a difference when going from native to managed code so it is not something I'd expect C++ developers to actually fall foul of, they just won't like it.

jk