Home > Net >  How to modify values in a C CLI Dictionary
How to modify values in a C CLI Dictionary

Time:12-16

I try to modify a value of a struct that is stored as a value in a Dictionary<> but I can change the value but it is not updated in the dictionary itself:

using namespace System::Collections::Generic;

value struct amplPhse {
   double ampl;
   double phse;
   int    indx;
   bool   actv;
};

Dictionary<String ^, amplPhse> constituent;

bool
activate(String^ comp, bool flag) { 
    bool     retv = false;
    amplPhse ^trgt;

    if (constituent.ContainsKey(comp)) {
        trgt = constituent[comp]; 
        trgt->actv = flag; 
        retv = true;
    }
    return retv;
}

// Fill Dictionary with data ... and activate a component
fillDictionary();
activate("Comp", true);

After calling the activate() function, trgt->actv is set to true but the corresponding element in the constituent Dictionary is not. It is unclear to me why the value->actv flag is not accessed in the dictionary.

CodePudding user response:

The problem is that your Dictionary elements are from a value struct which is a value type and not a reference type.
You can see some more general info here: What is the difference between a reference type and value type in c#?.

When you get a value from the Dictionary with this line:

trgt = constituent[comp];

You actually get a copy of the value stored in the Dictionary, and you modify this copy.

You can solve it in 2 ways:

  1. If you can modify amplPhse to be a ref class the code will behave as you expect:
ref class amplPhse {
public:
    amplPhse(bool a) : actv{ a } {}
    bool   actv;
};

int main()
{
    Dictionary<String^, amplPhse^> constituent;
    constituent.Add("k1", gcnew amplPhse{false});
    Console::WriteLine(constituent["k1"]->actv);
    amplPhse^ trgt = constituent["k1"];
    trgt->actv = true;
    Console::WriteLine(constituent["k1"]->actv);
    return 0;
}
  1. If you cannot modify amplPhse, you can wrap it in a refrence type, and store the wrapper in the Dictionary:
value struct amplPhse {
    bool   actv;
};

ref class amplPhseWrapper
{
public:
    amplPhseWrapper(amplPhse a) : ampl{ a } {}
    amplPhse ampl;
};

int main()
{
    Dictionary<String^, amplPhseWrapper^> constituent;
    constituent.Add("k1", gcnew amplPhseWrapper{amplPhse{ false }});
    Console::WriteLine(constituent["k1"]->ampl.actv);
    amplPhseWrapper^ trgt = constituent["k1"];
    trgt->ampl.actv = true;
    Console::WriteLine(constituent["k1"]->ampl.actv);
    return 0;
}

In both cases the output is:

False
True

I.e. the value in the Dictionary was modified.

  • Related