ProvincesByCountry is not explicit enough as it sounds like a one-to-one mapping of countries to provinces. When accessing ProvincesByCountry ["Germany"], I expected that one value is an object, not a list of objects.
My personal template is similar:
[Plural of a noun describing the value]By[Singular of a noun describing the key]
However, if the noun describing the meaning is plural in nature, then I use postfix arrays or lists, since in English you cannot plural. I personally always stick with arrays, regardless of the actual implementation of IEnumerable or IEnumerable <T> I use, whether it be List, Array, or something else.
In your case, it refers to:
ProvinceArraysByCountry
Tells what it is with scientific accuracy.
I apply this rule recursively if there are dictionaries as values. The access order then goes in reverse order to the word order in the name. Imagine you are adding planets:
ProvinceArraysByCountryByPlanet["Earth"]["Germany"][0] = "Bavaria" ProvinceArraysByCountryByPlanet["Earth"]["Germany"][1] = "Rhineland-Palatinate"
And finally, the last little touch. If such a dictionary compares the properties of the object and the objects themselves, I leave the word describing the object in the key section. Here is what I mean:
NodesByIndex[node.Index] = node;
I use this template unconditionally, which is good, since it leaves absolutely no room for guesswork. Con this sometimes generates fairly long names. But I have no idea how to always have explicit, but always short names. You must always compromise. And this, of course, is a matter of taste.
This pattern does not work (or at least you break the brain) when the keys are also dictionaries, or when you have a list of dictionaries, lists of dictionaries or some other crazy exotic things. But I do not remember that there were many levels of nesting, so I am pleased with this.