• 0

[C#] Assign values in dictionary


Question

Hi, I have say a

Dictionary<Color, int> myDict;

And I want to do this:

foreach (var kvPair in myDict) {
     kvPair.Value = 0; // not necessarily always 0, could be calculated per-value, whatever
}

But this triggers a compiler error:

Property or indexer 'System.Collections.Generic.KeyValuePair<Color,int>.Value' cannot be assigned to -- it is read only

How can I do this?

Link to comment
https://www.neowin.net/forum/topic/871176-c-assign-values-in-dictionary/
Share on other sites

14 answers to this question

Recommended Posts

  • 0

You can't alter a collection in a foreach loop, convert it to a normal for loop.

*Nevermind* that would be adding/removing the collection item...

for(int i=0; i< myDict.Values; i++)

{

kvPair....

}

  • 0
  On 01/02/2010 at 02:36, Calum said:

Does it work if you try the following?

foreach (KeyValuePair kvPair in myDict) {
     kvPair.Value = 0; // not necessarily always 0, could be calculated per-value, whatever
}

C# will infer System.Collections.Generic.KeyValuePair if you put var, so it's equivalent.

Actually I know of a way, but it's ugly and wastes CPU cycles:

foreach (Color color in Enum.GetValues(typeof(Color))) {
     myDict[color] = 0;
}

I'm wondering if I should use another container or if there's a more idiomatic way.

  • 0
  On 01/02/2010 at 02:41, Dr_Asik said:

C# will infer System.Collections.Generic.KeyValuePair if you put var, so it's equivalent.

Actually I know of a way, but it's ugly and wastes CPU cycles:

foreach (Color color in Enum.GetValues(typeof(Color))) {
     myDict[color] = 0;
}

I'm wondering if I should use another container or if there's a more idiomatic way.

Not using KVPs I don't think, since KVP objects are basically read-only once they have been instantiated for reasons which are beyond me (Why make the value member read-only?). I was going suggest using a SortedDictionary object since they're implemented as a binary tree and you could use a depth-first search to basically loop through the whole collection, but the OrderedDictionary object doesn't provide the facility to do it.

I was also going to suggest foreach'ing through the "Keys" collection, but I suspect that that would be less efficient than what you suggested.

I would say that it would be easier just to take the performance hit in this case, since the lookup time for a Dictionary is close to O(1) since its implemented as a hash table. Unless its a completely performance critical piece of code, in which case you might need to look into some of the other collection types.

  • 0

As previously stated, KeyValuePair<K, V> is a structure (read: not class) with read-only properties. The reasons behind this is that structures perform better when they are immutable. It's better to instantiate a new instance of a KeyValuePair<K, V> then to try and modify it's content. That being said, you can't modify an enumeration, this is also be design, so:

foreach (var pair in myDict) {
  pair.Value = 0; // This will fail because of read-only properties.
}

foreach (var pair in myDict) {
  pair = new KeyValuePair&lt;...&gt; // Won't work as you are modifying a read-only variable.
}

Whereas:

foreach (Color key in myDict.Keys) {
  myDict[key] = 0; // Make the modification here
}

... should work, as the you are enumerating over a collection of keys, not KeyValuePair<Color, int> items, and can modify the contents of the dictionary correctly.

  • Like 3
  • 0
  On 01/02/2010 at 09:18, Antaris said:

As previously stated, KeyValuePair<K, V> is a structure (read: not class) with read-only properties. The reasons behind this is that structures perform better when they are immutable.

And now I know! Thanks Antaris, have some Rep! :D

  • 0
  On 01/02/2010 at 09:18, Antaris said:

Whereas:

foreach (Color key in myDict.Keys) {
  myDict[key] = 0; // Make the modification here
}

... should work, as the you are enumerating over a collection of keys, not KeyValuePair<Color, int> items, and can modify the contents of the dictionary correctly.

Well, I'm afraid it doesn't, after testing it, I get a runtime error on the second iteration saying it cannot continue because the collection has been modified. So, back to iterating over Enum.GetValues for now. :unsure:
  • 0
  On 01/02/2010 at 18:28, Dr_Asik said:

Well, I'm afraid it doesn't, after testing it, I get a runtime error on the second iteration saying it cannot continue because the collection has been modified. So, back to iterating over Enum.GetValues for now. :unsure:

You get an error because the Keys collection is invalid after changing the value. Now, you can get around this by iterating over a list which temporarily holds the keys. That way, you get a List<Color> which contains all keys at that certain point. This list is not managed by the Dictionary and therefore won't be invalidated when you make changes to the Dictionary.

foreach (Color key in myDict.Keys.ToList()) {
    myDict[key] = 0; // Make the modification here
}

This appears to be the fastest and safest way to do this, so go and make good use of it. :)

  • 0
  On 01/02/2010 at 18:43, Calculator said:

foreach (Color key in myDict.Keys.ToList()) {
    myDict[key] = 0; // Make the modification here
}

This appears to be the fastest and safest way to do this, so go and make good use of it. :)

So are the keys cached in an array (or equivalent) then? I figured that it wouldn't be, whereas the enum values would just be known, making it less safe, but faster. Am I way off then?

  • 0
  On 01/02/2010 at 19:04, Majesticmerc said:

So are the keys cached in an array (or equivalent) then? I figured that it wouldn't be, whereas the enum values would just be known, making it less safe, but faster. Am I way off then?

Enum.GetValues() creates an array, while myDict.Keys.ToList() creates a List. Either way, allocation of a container every time. I don't like either, but it seems there's no other way.

It's a bit silly, but anyhow if I was writing for ideal performance I'd be using C++ so I guess it's tolerable.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • I think it's bloody great, old chap!
    • Not the deal that 2nd hand purchasers tend to look for - no.  It's cheaper than the sum of it's parts new - yes.  But people looking for 2nd hand, pre-built computers are rarely looking for what you are selling. Don't misunderstand; as an informed enthusiast I like that computer, and as an informed enthusiast I am often asked "My son wants a gaming PC and here's my budget" - in which case, as an informed enthusiast I would totally point them in this sort of direction.  But I am not the mass market, hence you may well have to wait longer for a sale. If you're looking for speed - then breaking it into parts is likely to pay off better on that front, as there will be more people who suit that market and their likelihood of buying 2nd hand is more fruitful.  But - chore!
    • What is the purpose of this article? You didn't even mention that CPU is powering it, so we don't know what GPU/iGPU it has. We don't know if the memory is on chip, on the motherboard, is expandable or replaceable. And that's only the internals. Display type, resolution, brightest you didn't even mention the DPI. Without one or more if these capabilities no one who reads these strung together words will know if they should or shouldn't buy it. The only HINT is from the sticker on the photo of the laptop. Q: what do you get for wasting people's time? Their must be some value or you wouldn't have wasted your time either.
    • That is some storage. I have an old F4-210 and it works well for what it is, just a shame Terramaster will not update the software for it.
  • Recent Achievements

    • Week One Done
      Taylan earned a badge
      Week One Done
    • One Month Later
      Taylan earned a badge
      One Month Later
    • Week One Done
      Yianis earned a badge
      Week One Done
    • Veteran
      Travesty went up a rank
      Veteran
    • One Month Later
      somar86 earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      506
    2. 2
      ATLien_0
      260
    3. 3
      +Edouard
      186
    4. 4
      +FloatingFatMan
      176
    5. 5
      snowy owl
      132
  • Tell a friend

    Love Neowin? Tell a friend!