There is no way to get the size of a managed object, it differs from implementation to implementation.
See this link for more details: Size of a managed object
For an inaccurate estimate you can try using GC.GetTotalMemory(false)
just before the HashTable is initialized and right after it is filled with data:
Console.Write("How many entries would you like to store in the Hashtable?:");
int hashTableEntries;
int.TryParse(Console.ReadLine(), out hashTableEntries);
var memBeforeHashInit = GC.GetTotalMemory(true);
var hashTable = new Hashtable();
for (int i = 0; i < hashTableEntries; i++)
hashTable.Add(i, i);
var memAfterHashInit = GC.GetTotalMemory(false);
var diff = memAfterHashInit - memBeforeHashInit;
Console.WriteLine("Memory used since startup: {0} bytes" +
"\r\n" +
"Hashtable entries: {1}" +
"\r\n" +
"Press any key to exit", diff, hashTableEntries);
Console.ReadLine();
As it appears, that once a Hashtable is initialized, 8192 bytes are allocated in memory, it also appears that it allocates memory for 64 of its elements, giving 128 bytes per element. As soon as you add the 65th element to the Hashtable it reserves another 8192 bytes for another 64 elements.
It may differ on another system, it's up to the CLR to decide that :)