Generic collections are definitely preferred due to their expressiveness. One thing to keep in mind if changing from the non-generic collections is that sometimes the behavior may be different than you expect. For example, using the indexer on a Hashtable vs. a Dictionary will act differently for values that are not present. Hashtable will return null while Dictionary will throw.
Hashtable ht = new Hashtable();
ht.Add(1, "one");
string s1 = ht[1; // s1="one"
string s2 = ht[2]; // s2=null
var dic = new Dictionary<int, string>();
dic.Add(1, "one");
string s1 = dic[1]; // s1="one"
string s2 = dic[2]; // throws KeyNotFoundException
A common way to handle this is to use the following technique:
string s = null;
if (dic.TryGetValue(k, out s))
{
// if we're here, k was found in the dictionary
}
This will show up only at runtime so it's worth knowing ahead of time.