Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Why does this return KeyNotFoundException?

Discussion in 'Scripting' started by howaboutno000, Jan 8, 2021.

  1. howaboutno000

    howaboutno000

    Joined:
    Nov 13, 2020
    Posts:
    20
    Code (CSharp):
    1. Dictionary<KeyCode, Action> localDict = new Dictionary<KeyCode, Action>();
    2. localDict[KeyCode.A] += () => Debug.Log("yep");
    Second line fails, why?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    You can make a delegate and just add listeners to it.

    But this is a dictionary retrieval problem: you can't make a delegate by asking for something that isn't IN the dictionary.

    So first add a System.Action to the dictionary if the key doesn't exist.
     
    howaboutno000 and PraetorBlue like this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    Your code is short for this:
    Code (CSharp):
    1. Action existingAction = localDict[KeyCode.A];
    2. existingAction += () => Debug.Log("yep");
    You get the exception because There is no entry for KeyCode.A in the dictionary yet.
     
    howaboutno000 and Kurt-Dekker like this.
  4. howaboutno000

    howaboutno000

    Joined:
    Nov 13, 2020
    Posts:
    20
    How do I create/add Action within Dictionary?

    Code (CSharp):
    1. Dictionary<KeyCode, Action> localDict = new Dictionary<KeyCode, Action>();
    2. if (localDict.TryGetValue(KeyCode.A, out var p)) p += () => Debug.Log("yep");
    3. else
    4. {
    5.    p = new Action(); // what?
    6.    p += () => Debug.Log("yep");
    7. }
     
  5. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    Code (CSharp):
    1. Dictionary<KeyCode, Action> localDict = new Dictionary<KeyCode, Action>();
    2. Action toAdd = () => Debug.Log("yep");
    3. if (localDict.TryGetValue(KeyCode.A, out var p)) {
    4.    p += toAdd;
    5. }
    6. else {
    7.    localDict[KeyCode.A] = toAdd;
    8. }
    Edit: This code is actually incorrect. See below in the thread for more information
     
    Last edited: Jan 8, 2021
    Kurt-Dekker and howaboutno000 like this.
  6. howaboutno000

    howaboutno000

    Joined:
    Nov 13, 2020
    Posts:
    20
    Thank you.
     
  7. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    VolodymyrBS likes this.
  8. VolodymyrBS

    VolodymyrBS

    Joined:
    May 15, 2019
    Posts:
    150
    Small edit to this code. p+=toAdd will not modify action in dictionary because delegates are immutable and this code modify only local p variable. to modify record in dictionary you should use code like this
    Code (CSharp):
    1. Dictionary<KeyCode, Action> localDict = new Dictionary<KeyCode, Action>();
    2. Action toAdd = () => Debug.Log("yep");
    3. if (localDict.TryGetValue(KeyCode.A, out var p)) {
    4.    p += toAdd;
    5. }
    6. else
    7. {
    8.     p = toAdd;
    9. }
    10. localDict[KeyCode.A] = p;
    11. }
     
    Kurt-Dekker and PraetorBlue like this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    Hey Volod, thanks a lot for this clarification (here and in the other thread)... I didn't understand this fundamental nature and now that you explain it, it makes complete sense with all past observations.
     
    PraetorBlue likes this.