I have been searching for a way to save the references of variables of various types into a dictionary, together with a corresponding key. Then i would like to modify the instance of the variable by accessing its reference through the dictionary by its key.
For storing the references, i tried to use <object>
, but without success. Neither Dictionaries nor Lists accept anything like Dictionary<string, ref int>
.
The following code compiles, but seems to update the variables by value only. Any ideas or workarounds?
Here's the (tested) code:
class Test1
{
IDictionary<string, object> MyDict = new Dictionary<string, object>();
public void saveVar(string key, ref int v) //storing the ref to an int
{
MyDict.Add(key, v);
}
public void saveVar(string key, ref string s) //storing the ref to a string
{
MyDict.Add(key, s);
}
public void changeVar(string key) //changing any of them
{
if(MyDict.GetType() == typeof(int))
{
MyDict[key] = (int)MyDict[key] * 2;
}
if(MyDict.GetType() == typeof(string))
{
MyDict[key] = "Hello";
}
}
}
And this is how i call the methods of the class
Test1 t1 = new Test1();
int myInt = 3;
string myString = "defaultString";
Console.WriteLine(myInt); //returns "3"
Console.WriteLine(myString); //returns "defaultString"
t1.saveVar("key1", ref myInt);
t1.saveVar("key2", ref myString);
t1.changeVar("key1");
t1.changeVar("key2");
Console.WriteLine(myInt); //should return "6"
Console.WriteLine(myString); //should return "Hello"
In C# object is one of the root and parent class for all the subclasses; based on the requirement, we can able to convert the object to other types like a dictionary, strings like that dictionary is one of the generic collection class that can be used for to store the datas as key/value pairs by using the System.
One can only put one type of object into a dictionary. If one wants to put a variety of types of data into the same dictionary, e.g. for configuration information or other common data stores, the superclass of all possible held data types must be used to define the dictionary.
Examples of reference books include: almanacs, atlases, dictionaries, directories, encyclopedias and indexes.
A Dictionary object is the equivalent of a PERL associative array. Items, which can be any form of data, are stored in the array. Each item is associated with a unique key. The key is used to retrieve an individual item and is usually an integer or a string, but can be anything except an array.
Apart from the problem Kevin points out, you need to wrap your value types in some kind of reference type.
The problem, as you've figured out, is that generic types don't work with the ref keyword, and when you assign a new value type into your dictionary, it's replacing the reference with a different reference, not updating it. There is no way to retain the ref semantics once you assign it to the dictionary.
But, what you could do is something like this, simply wrap the value type in a reference type:
public class MyRef<T> {
public T Ref {get;set;}
}
public class Test1
{
Dictionary<string, object> MyDict = new Dictionary<string, object>();
public void saveVar(string key, object v)
{
MyDict.Add(key, v);
}
public void changeVar(string key, object newValue) //changing any of them
{
var ref1 = MyDict[key] as MyRef<int>;
if (ref1 != null) {
ref1.Ref = (int)newValue;
return; // no sense in wasting cpu cycles
}
var ref2 = MyDict[key] as MyRef<string>;
if (ref2 != null) {
ref2.Ref = newValue.ToString();
}
}
public void DoIt()
{
var v = new MyRef<int> { Ref = 1 };
saveVar("First", v);
changeVar("First", 2);
Console.WriteLine(v.Ref.ToString()); // Should print 2
Console.WriteLine(((MyRef<int>)MyDict["First"]).Ref.ToString()); // should also print 2
}
}
The best solution I can think of for this is to store delegates in the dictionary that will allow you to retrieve and modify the variables.
Let’s start by declaring a type that contains a getter and a setter delegate:
sealed class VariableReference
{
public Func<object> Get { get; private set; }
public Action<object> Set { get; private set; }
public VariableReference(Func<object> getter, Action<object> setter)
{
Get = getter;
Set = setter;
}
}
The dictionary would have the type:
Dictionary<string, VariableReference>
To store a variable, say foo
of type string
, in the dictionary, you’d write the following:
myDic.Add(key, new VariableReference(
() => foo, // getter
val => { foo = (string) val; } // setter
));
To retrieve the value of a variable, you’d write
var value = myDic[key].Get();
To change the value of a variable to newValue
, you’d write
myDic[key].Set(newValue);
This way, the variable that you’re changing is genuinely the original variable foo
, and foo
can be anything (a local variable, a parameter, a field on an object, a static field... even a property).
Putting this all together, this is what the class Test1
would look like:
class Test1
{
Dictionary<string, VariableReference> MyDict = new Dictionary<string, VariableReference>();
public void saveVar(string key, Func<object> getter, Action<object> setter)
{
MyDict.Add(key, new VariableReference(getter, setter));
}
public void changeVar(string key) // changing any of them
{
if (MyDict[key].Get() is int)
{
MyDict[key].Set((int)MyDict[key].Get() * 2);
}
else if (MyDict[key].Get() is string)
{
MyDict[key].Set("Hello");
}
}
}
// ...
Test1 t1 = new Test1();
int myInt = 3;
string myString = "defaultString";
Console.WriteLine(myInt); // prints "3"
Console.WriteLine(myString); // prints "defaultString"
t1.saveVar("key1", () => myInt, v => { myInt = (int) v; });
t1.saveVar("key2", () => myString, v => { myString = (string) v; });
t1.changeVar("key1");
t1.changeVar("key2");
Console.WriteLine(myInt); // actually prints "6"
Console.WriteLine(myString); // actually prints "Hello"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With