5

A List has separate properties for getting the Count and its Capacity. Dictionaries, like all collections, have the Count property too, and it has a capacity because it has several constructors that allow you to specify it and the documentation for the Add method mentions it. However, i don't see any way of querying the Dictionary for what its current capacity is.

Even if there is no way of getting a Dictionary's current capacity, is there any way to predict when a reallocation might occur?

Tubeliar
  • 836
  • 7
  • 20
  • 2
    related: http://stackoverflow.com/questions/2760931/initial-capacity-of-collection-types-e-g-dictionary-list – Mitch Wheat Oct 06 '16 at 07:08
  • 1
    A dictionary works different, it uses buckets which will contain items with similar hashcodes. – Maarten Oct 06 '16 at 07:09
  • 1
    related: http://stackoverflow.com/a/24366862/261050 – Maarten Oct 06 '16 at 07:09
  • 1
    I think you have the problem the wrong way round. If you know the total size upfront, pre-allocate on creation – Mitch Wheat Oct 06 '16 at 07:09
  • 3
    Dictionaries, as hash tables, work fundamentally different to lists / dynamic arrays. The capacity is not used the way you probably think it is. Why do you want to know it, what do you think will knowing it help you with? – poke Oct 06 '16 at 07:11
  • Indeed, i didn't think of how using buckets affects a concept like capacity. But since the documentation speaks of it i assumed it had a capacity as a single queryable number. The reason i want to know it is because i want to know if an Add invocation will trigger a reallocation. I'm using it in a game and my dictionary grows large enough that the reallocation causes a noticeable judder in the frame rate. – Tubeliar Oct 06 '16 at 07:17
  • For this sort of internal stuff, [the source](https://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs) often helps. Specifically, look at the implementation of `Insert`. The dictionary resizes when a new value is added and `freeCount == 0 && count == entries.Length`, or based on collision count when `FEATURE_RANDOMIZED_STRING_HASHING` is enabled (which is the case on .NET Core). Even using reflection, this isn't so easy to detect from code. You may be better off with a custom type if you can't pre-predict capacity well. – Jeroen Mostert Oct 06 '16 at 07:26

1 Answers1

1

Dictionaries do not work like lists exactly. If you examine the source code provided by microsoft. You can find multiple private fields that might be helpful.

Be aware that this is an encapsulated implementation detail, you should not depend on it in your production code as names, behavior of private and internal members might change without prior notice!

You have internal arrays int[] buckets and Entry[] entries. You also have int freeList and int freeCount. You can use reflection to play around these.

To answer your question, YES a reallocation is triggered on each insert and here is the actual code:

int index;
if (freeCount > 0)
{
    index = freeList;
    freeList = entries[index].next;
    freeCount--;
}
else
{
    if (count == entries.Length)
    {
        Resize();
        targetBucket = hashCode % buckets.Length;
    }
    index = count;
    count++;
}
Zein Makki
  • 29,485
  • 6
  • 52
  • 63