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:
- If you can modify
amplPhse
to be aref 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;
}
- If you cannot modify
amplPhse
, you can wrap it in a refrence type, and store the wrapper in theDictionary
:
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.