Just keep repeating: “C# is not Java. C# is not C++.”
Vicente Cartas’s latest blog post on Singleton’s in C# (original post in Spanish) illustrates something very important for learning C# well – there are subtle, but very important differences in C# which are very valuable to learn if you’re coming from a Java or C++ background. This is a classic example – the traditional C++ forms of the Singleton pattern are not appropriate in C#.
C# and .NET make life a lot easier, in a lot of ways… but it’s critical to understand the subtle nuances caused by the abstraction layers .NET provides.
This pops its head up in many places – one example is in the classic design patterns. C# offers some great alternatives, with surprising consequences, to some of the classic forms of design patterns. A nice example is the Visitor Pattern. Judith Bishop and R. Nigel Horspool wrote a paper illustrating some interesting alternative implementations of the visitor pattern using C# 3.0. I particularly like her delegate implementation. The Observer Pattern is another great example – in C++, this pattern required quite a bit of implementation work. In C#, the observer pattern is a core part of the language itself, down to having language keywords to describe it: event and delegate.
Memory management is another place C# dramatically differs from C++. Many people tout the garbage collector and not having to free memory as a great advantage of C#, and it is, but that isn’t the only place where memory management changes the rules. The specific implementation of the garbage collector alters memory allocation, for example. In C++, constructing a new object on the heap is a fairly expensive operation. If you’re making performant code, you need to do everything you can to keep all memory allocations on the stack in your loops, or you’ll dramatically impact your runtime speed.
In C#, the rules completely change. Memory allocations in C# are (relatively) cheap – no longer do you need to worry (as much) about allocating objects in the middle of loops. This changes the way you can approach an algorithm, and can have a huge impact on the resulting code.
I guess my main comment is: If you’re planning to really delve into C#, treat it like a separate language from what you’ve learned before. Read a good book that really discusses the core aspects that sets C# and .NET apart, such as C# in Depth or CLR via C#.