We've been talking a lot lately about managing breaking changes on our team, so I spent some time reading Erip Lippert's excellent series on the topic. Whilst doing so, I learned something about C# that I was at least somewhat embarrased not to know. If a method call matches any viable overload in the most-derived class, then that method will be called, regardless of if there is a better match in any base class. Eric explains the reasons which are very obvious five seconds after you've read them. That was thing one.
Thing two was that virtual method overrides are considered as belonging to the class that declares the virtual, not to the overriding class. This was directly counter to my mental model of methods occupying slots, so I was more surprised.
I've considered C# to be my main dev language now for about six years, which isn't quite as long a time as I thought the same about C/C++, but it still suprises me that I'm discovering such wrinkles in what is ostensibly a smaller, simpler language. I'm putting this down to the fact that C++ was designed more to favour the program developed in the language, whereas C# is designed more to favour the engineering the language enables.