• 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

    • Err more info required... Are you using the built-in VPN client? PowerShell > Batch. Either way, the script will most likely use rasdial.
    • The viewing figures in season 2 plummeted after 1 of the main characters died in season 2 episode 1. I think hbo is regretting listening to him so they got rid of him.
    • Google Workspace now lets you use custom AI Gems directly in Docs, Gmail, and more by Paul Hill Google Workspace users can now access Gems from the side panel of Google Docs, Slides, Sheets, Drive, and Gmail. Previously, Gems could only be accessed from the Gemini app directly. For anyone not familiar with Gems, they’re a more advanced feature in Gemini where you can make your own chatbots, powered by Gemini, with custom instructions. If you’re interested in learning more about them, check out my editorial from April, where I argue custom AI bots are the best thing about generative AI and how to create your own bots. The decision to make Gems available across Google Workspace has the potential to significantly speed up people’s workflows if they’ve started using Gems already. If you’ve never made a Gem, Google has several pre-made ones including a Brainstormer, Writing editor, Coding partner, and Learning guide. Google Workspace users can leverage Gems in an almost infinite number of ways. For example, imagine if you’re a teacher in whatever country and you have to make lesson plans for your class that must follow a certain structure, you can use natural language to program a gem to expect certain inputs from you (such as grade, subject, topic etc) and get an output that follows the required guidelines. If you’re a journalist, you could create a gem to quickly strip out the key bits of news from a press release or if you’re a student you can create a bot to break down complicated subjects into something easier to understand. The possibilities are nearly endless and now the Gems you make are even more accessible. Google mentioned that Gems can be accessed via the side panel of all supported Workspace applications and can be used across Workspace capabilities including @ mentioning, accessing files and folders, and more. If you need to create a Gem, you’ll still need to do that on the Gemini website. To get started with Gemini in Google Workspace, just click the “Ask Gemini” (spark button) in the top-right corner. Google said that the Gems feature rollout is an extended rollout which means it might take more than 15 days to get the feature. Admins out there do not need to do anything and there are no specific admin controls in the side panel for Gems or Gemini.
    • Microsoft changes hit Teams Android devices: Disable Entra ID policy to restore sign-in by Paul Hill As part of its Secure Future Initiative, Microsoft has deployed a new Entra ID Conditional Access policy targeting Device Code Flow authentication. Unfortunately, it has led some Microsoft Teams-certified Android devices (Teams Rooms on Android, Teams Phones, Teams Panels, and Teams Displays) to be logged out and signing back in can be a bit fiddly so guidance has been shared. Microsoft said that it shared previous guidance which explained how to exclude Android devices, but it seems some admins didn’t catch this as many devices were not excluded and have been signed out. It’s important to realize that this is not a bug, it’s a security feature. However, the move could have been better communicated. To sign the devices back in, you can do so manually. However, if the devices are remote you’ll need to follow these steps: By disabling the “Block device code flow” policy in step 1, it will change everything back to how it was before Microsoft decided to enable it to boost security. This will allow you to get those affected Android devices logged back in again. Also pay special attention to step 2 which says you might need to reboot your device three times. Once you have your Android devices logged in again, it’s probably a good idea to follow Microsoft’s previous guidance and add these to an exclusion list before re-enabling the “Block device code flow” policy. Microsoft recommends only allowing DCF where it’s absolutely necessary and then blocking it elsewhere. The best thing to do is to add your Teams Android device to the exclusion list - this will allow these devices to operate normally, while boosting overall security. If you’re an admin and have been impacted by this, be sure to take proactive measures to avoid disruptions in the future.
  • Recent Achievements

    • Reacting Well
      SteveJaye earned a badge
      Reacting Well
    • One Month Later
      MadMung0 earned a badge
      One Month Later
    • One Month Later
      Uranus_enjoyer earned a badge
      One Month Later
    • Week One Done
      Philsl earned a badge
      Week One Done
    • Week One Done
      Jaclidio hoy earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      434
    2. 2
      ATLien_0
      158
    3. 3
      +FloatingFatMan
      146
    4. 4
      Nick H.
      65
    5. 5
      +thexfile
      62
  • Tell a friend

    Love Neowin? Tell a friend!