One of the problems would be that in many cases, the key for the hash table would be a string. So the consumers of the method would have to know before hand which keys to use to extract the data. This would give the potential for errors due to mispellings when accessing the data.
Another drawback is refactorability. If you decide later on to change the name of a member, you then have a bunch of magic strings that also need to change. It's a lot simpler to rename a class member using refactoring tools provided by most good IDE's. With a hash table you'd likely have to do a find/replace operation across all source files which could be problematic.
Lastly, you will lose compile time checking of the member access - both in terms of name and type. The latter is not such a problem if your hash table only contains one type of obejct, but if it contains many (even in the same hierarchy chain) you really want to leverage the type system of your language and get compile time checking there. In most IDE's you'll have some kind of intellisense/autocomplete features - these work by looking at the type system, but they wont be able to help you with hash table keys.
As for times when it would be appropriate to return a hash table (or other such collection of key value pairs), you would use this when both the values and the keys are not known at compile time. For example, if you have a method which parses a query string and returns the keys & corresponding values, a hash table would be a good choice. In this case you would also want to think about returning some kind of immutable or readonly hash table.
Edit - Most of the points raised in this answer cease to apply when you're talking about dynamic languages :)