While blog-surfing recently I ended up at an article about the ups and downs of Hungarian notation: "Hungarian Notation - The Good, The Bad, and The Ugly." The Good makes some good points, although I personally I don't believe that they are enough to overcome its shortcomings. The Bad is poorly written, in my opinion, and does not add anything substantial to the argument. The Ugly, however, is very well written and makes several good points. It expresses my primary argument against Hungarian notation quite clearly:
"Hungarian notation encodes type information into variable names. This is very useful in languages that don't keep track of types information for you. But in C++ or Eiffel it is completely redundant. Thus, the notation simply adds to obscurity."
It also expresses a point which, although I was aware of it implicitly, I had not been able to express previously:
"Hungarian notation is, when all is said and done, a commenting technique. And the one great law of comments is that they lie."
This is precisely true. Hungarian notation, at least in the form that most of us learned in school, simply says "this variable is this type." Its like a comment. But comments quickly become outdated as programs change, and often in the end they are more misleading than helpful.
I do still use an underscore before class-level variables, but this is mostly to distinguish them from the properties which they typically represent (In C# I could rely on casing differences to make the distinction, but going down that road is just asking for death-by-typo).