I'd be the first to admit that coming from C++ to C# was hard for me, because C++ had been my core language, and while I learned things like Python, they were so obviously NOT C++, that I just accepted they were different. C# is named after C++, and goes out of it's way to look like C++, so when it was plainly very different, I often took it hard. This was, obviously, my fault.
However, there are things about C# that still make no sense to me. I still hate that C# won't allow fallthrough in case statements, such as
When I asked the C# team, I was told that C# will always err on the side of being easy for beginners, rather than being powerful. I believe a strength of C++ is that it assumes skill on the part of the programmer, rather than treating him like an idiot.
I was also astounded at the lack of generics support in C# 1.0. I still talk to people on forums using ArrayList today, despite generic containers having been in for some time now. The generics support we have is very limited compared to C++ templates, I don't see how 1.0 could not have contained an engine that generates a typed List class, for every templated argument given. That's basically all we have now, right ? Although at least the CLR means that you don't end up with a ton of different classes in your exe, as you did in C++.
In addition, in C++, we had the STL, with a vector and a list class. The vector is an array class, which means fast random lookups, but slow inserts. A list has the opposite O notation. In C#, we were given a class called ArrayList. OK, is it an array, or is it a list ? ( It's a list, by the way ). To my knowledge ( and I just googled again to make sure ), there's still no array class, although you can arguably just use an array, and HashSet only arrived in .NET 3.5. I don't understand why such basic things were not implimented.
I will say that I love LINQ and I love that C# is moving past being a poor mans C++, and establishing it's own set of power features.
One thing I asked the C# team for many times, was optional parameters. They want to keep the language simple, yet instead of having the compiler generate a method like
bool SomeMethod(int n)
return SomeMethod(n, "The default value");
they want me to write it and maintain it instead ? In C# 4.0, they are finally implimenting this, and doing it all the way, with named optional parameters, which is pretty cool, but it's sure been a long wait, and I don't see what damage an intermittent, non named parameter version could have done in the meantime.
Which brings me to my main point. One thing that took some getting used to in C#, is that classes are always passed by reference. If you pass me a class instance, and I change it, I changed it for you, too. So, it seems to me that if I were writing a library, I would want to create an interface that provides a contract to my users - I am not going to change this object, I can be trusted to return it in the state it was given to me. The fact that they kept a const keyword, but made it mean something totally different in C# to C++ threw me at first, but I eventually found the readonly keyword, I just don't see why it can't be applied to parameters on a method definition. Sure, it's syntactic sugar, it doesn't change what the method does, but, writing code that a computer can understand is EASY. The thing we need most to focus on, is writing code that HUMANS can understand and trust. Code that is maintainable, AND that explains itself well to a first time user, should always be the goal.
I do see that there's a level of complexity there, if a method takes a const parameter, passes it to another method, which passes it somewhere else. And I can see that the solution to the fallthrough problem in case statements apparently being goto means that we're encouraged to write spaghetti in C#, but, I still find myself from time to time wishing that when I write a method, I could actually remind others, and have the compiler remind me, that I wanted to pass an object into a method, without that method changing the object in any way. The only alternative I can see is to write and pass in a wrapper class which only allows getting of properties in the contained class. And, while I used to spend time writing strongly typed containers in C# 1.0, even I am not pedantic enough to do that.
And if anyone tells you they are learning C#, and know C++, the best piece of advice to give, is to say, C# is not based on C++, it's Java on steroids.