I've been writing apps in mostly C# for several years now. Of course I've also been doing drivers and kernel work in C or C++, and that has only improved my ability to write, debug and understand managed code in ways that pure managed developers will never really get. Hell, I pretty much believe that if your managed code doesn't require allowing unsafe code then it could probably be done better.
Well for a few months now I've been neck-deep in a C++ application. It was started using MFC, which tends to give me a rash just by saying the letters, but it was a customer decision not mine. At any rate, I was doing some work with a RAS class where I needed any number of consumers to be able to be notified of any changes in the RAS dial status (dialing, connecting, authenticating, etc.).
Imagine a C# class for RAS that will expose events for when the dial staus changes. THe first thing you'd need is a delegate, right?
In C# you'd have this (assuming DialStatus is an enum):
delegate void DialStatusChange(DialStatus dialStatus);
Well the c++ I wrote (without even thinking about C#) looked eerily familiar:
typedef void(*DIAL_STATUS_DELEGATE)(DialStatus newStatus);
In C# you'd use the += or -= operators for adding an event handler to a classes event, so we get spoiled. In VB, you call AddHandler with the event name and then the address of the handler. Well my C++ had a private vector of function pointers (which the CF maintains internally):
std::vector <DIAL_STATUS_DELEGATE> ConnectionManager::m_statusCallbackList;
And then I added methods for adding and removing handlers to the class:
void ConnectionManager::StatusAddHandler(DIAL_STATUS_DELEGATE callback)
{
m_statusCallbackList.push_back(callback);
}
void ConnectionManager::StatusRemoveHandler(DIAL_STATUS_DELEGATE callback)
{
std::vector<DIAL_STATUS_DELEGATE>::iterator iterator;
for(iterator = m_statusCallbackList.begin() ; iterator != m_statusCallbackList.end() ; iterator++)
{
if((*iterator) == callback)
{
m_statusCallbackList.erase(iterator);
break;
}
}
}
And how about usage? In C#, our event-exposing class would have a defined event:
event DialStatusChange OnStatusChange;
and then when we want to raise the event (assume it's multicast) from our app, we'd do something like this:
if (OnStatusChange != null)
{
foreach (DialStatusChange dsc in OnStatusChange.GetInvocationList())
{
dsc(newStatus);
}
}
Well my C++ didn't need the event declaration, but raising the "event" (which is simply calling a function pointer callback) looked like this:
std::vector<DIAL_STATUS_DELEGATE>::iterator iterator;
recheck2:
for(iterator = m_statusCallbackList.begin() ; iterator != m_statusCallbackList.end() ; iterator++)
{
if(IsBadCodePtr((FARPROC)(*iterator)))
{
// invalid callback found (someone hooked us then died without unhooking)
m_statusCallbackList.erase(iterator);
goto recheck2;
}
(*iterator)(status);
}
Now this was just off the top of my head, so maybe there are improvements that could be made, but it kind of surprised me how I'd taken the concepts I really learned in C# and translated them back to my C++ code. So yes, writing C# can make you a better C++ developer.