Dictionary By Reference

N

NullQwerty

Hi folks,

I have a Dictionary which contains a string key and an object value. I
want the object value to point to a property in my class and I want it
to be by reference, so that later on I can change the value of the
property through the dictionary.

I am having difficulty making the value be by reference. Is this
possible? I've even tried unsuccessfully to use unsafe code with
pointers.

It's easier to understand what I'm looking for if you just look at the
below. Here's what I have:

private int _MyProp1 = -1;
public int MyProp1
{
get
{
return _MyProp1;
}
set
{
_MyProp1 = value;
}
}

public Dictionary<string, object> MyDict = new Dictionary<string,
object>();
//Note value is of type object because it could be an int property or
string property or...

public void AddPropsToDict()
{
MyProp = 1;
// Want below to take MyProp by Ref
MyDict.Add("propID", MyProp);
}

public void UpdateValues()
{
MyDict["propID"] = 3;
// Below Prints 3
Console.WriteLine(MyDict["propID"]);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyProp);

/*
// Alternative way does not work either
object oProp = MyDict["propID"];
oProp = 3
// Below Prints 3
Console.WriteLine(oProp);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyDict["propID"]);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyProp);
*/
}

Thanks!
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

I'm not very clear of why you want this in the first place, but I can tell
you that you cannot do it. Only if the property is a reference type you
could do something like that.

Now a possible workaround could be if you instead of keeping a reference to
the property itself keep a reference to the instance containing the
property.

In the case that this is not possible (or desirable) you could keep a
reference to a PropertyInfo of that property.
 
A

Andreas Mueller

Hi folks,

I have a Dictionary which contains a string key and an object value. I
want the object value to point to a property in my class and I want it
to be by reference, so that later on I can change the value of the
property through the dictionary.

I am having difficulty making the value be by reference. Is this
possible? I've even tried unsuccessfully to use unsafe code with
pointers.

It's easier to understand what I'm looking for if you just look at the
below. Here's what I have:

private int _MyProp1 = -1;
public int MyProp1
{
get
{
return _MyProp1;
}
set
{
_MyProp1 = value;
}
}

public Dictionary<string, object> MyDict = new Dictionary<string,
object>();
//Note value is of type object because it could be an int property or
string property or...

public void AddPropsToDict()
{
MyProp = 1;
// Want below to take MyProp by Ref
MyDict.Add("propID", MyProp);
}

public void UpdateValues()
{
MyDict["propID"] = 3;
// Below Prints 3
Console.WriteLine(MyDict["propID"]);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyProp);

/*
// Alternative way does not work either
object oProp = MyDict["propID"];
oProp = 3
// Below Prints 3
Console.WriteLine(oProp);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyDict["propID"]);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyProp);
*/
}

Thanks!

Hi,

without knowing more details about what you want to achieve I can think
of 3 different approaches.

1) If your dictionary is used inside your class, you can store your
values inside the dictionary and let the property access the values of
the dictionary:

class Test1
{
private IDictionary<string, object> myDict =
new Dictionary<string, object>();
public int MyProp
{
get
{
object o = MyDict["propID"];
if(o == null)
{
o = -1;
MyDict.Add("propID", o);
}
return (int)o;
}
set{ MyDict["propID"] = value; }
}

private IDictionary<string, object> MyDict
{
get { return myDict; }
}

public void UpdateValues()
{
MyDict["propID"] = 3;

Debug.Assert(MyProp == 3);

}
}

// ... Usage
Test1 t1 = new Test1();
t1.UpdateValues();

2) Use Reflection to access the properties in the same manner as a
function pointer map in C/C++:

class Test2
{
private IDictionary<string, PropertyInfo> myDict =
new Dictionary<string, PropertyInfo>();
private int prop = -1;
public int MyProp
{
get { return prop; }
set { prop = value; }
}

private IDictionary<string, PropertyInfo> MyDict
{
get { return myDict; }
}

public void AddPropsToDict()
{
MyProp = 1;

MyDict.Add("propID", GetType().GetProperty("MyProp"));
}

public void UpdateValues()
{
MyDict["propID"].SetValue(this, 3, null);;

Debug.Assert(MyProp == 3);

}
}

// ... Usage
Test2 t2 = new Test2();
t2.AddPropsToDict();
t2.UpdateValues();

3) Build a reference type integer that (almost) behaves like a normal
integer. By almost I mean that this class behaves like a primitive, but
is *not* immutable. This might be error prone, so if possible I would
recomend to hide it from the public interface.

class Integer
{
public Integer(int val)
{
IntValue = val;
}
private int val;
public static implicit operator int(Integer intRef)
{ return intRef.IntValue; }
public static implicit operator Integer(int i)
{ return new Integer(i); }
public static bool operator==(Integer lhs, Integer rhs)
{ return Equals(lhs, rhs); }
public static bool operator !=(Integer lhs, Integer rhs)
{return !Equals(lhs, rhs); }

internal int IntValue// This one is smells.
{
get { return val; }
set { val = value; }
}

public override bool Equals(object o)
{
if(o is int)
return val == (int) o;

Integer rhs = o as Integer;
return rhs != null
? IntValue.Equals(rhs.IntValue)
: false;
}
public override int GetHashCode()
{ return IntValue.GetHashCode(); }
}

class Test3
{
private IDictionary<string, object> myDict = new
Dictionary<string, object>();
private Integer prop = -1;
public Integer MyProp
{
get { return prop; }
set { prop = value; }
}

private IDictionary<string, object> MyDict
{
get { return myDict; }
}

public void AddPropsToDict()
{
MyProp = 1;

MyDict.Add("propID", MyProp);
}

public void UpdateValues()
{
((Integer)MyDict["propID"]).IntValue = 3;

Debug.Assert(MyProp == 3);

}
}

Test3 t3 = new Test3();
t3.AddPropsToDict();
t3.UpdateValues();

HTH,
Andy
 
J

Jon Skeet [C# MVP]

I have a Dictionary which contains a string key and an object value. I
want the object value to point to a property in my class and I want it
to be by reference, so that later on I can change the value of the
property through the dictionary.

You can't do that. Well, you can make the dictionary a map from a
string to a PropertyInfo, but that's the only way of doing it.
 
N

NullQwerty

Let me first just say Thank You. That is by far the most thorough
response I've ever received from a posting.

I went forward with the approach of removing the private member and
having that relate back to the dictionary index. Before reading your
post I had begun implementing the PropertyInfo approach, but the other
way is much more straight forward (and I keep hitting myself in the
head saying 'Duh...why wasn't I doing that to begin with').

Thanks again for the excellent response!


Andreas said:
Hi folks,

I have a Dictionary which contains a string key and an object value. I
want the object value to point to a property in my class and I want it
to be by reference, so that later on I can change the value of the
property through the dictionary.

I am having difficulty making the value be by reference. Is this
possible? I've even tried unsuccessfully to use unsafe code with
pointers.

It's easier to understand what I'm looking for if you just look at the
below. Here's what I have:

private int _MyProp1 = -1;
public int MyProp1
{
get
{
return _MyProp1;
}
set
{
_MyProp1 = value;
}
}

public Dictionary<string, object> MyDict = new Dictionary<string,
object>();
//Note value is of type object because it could be an int property or
string property or...

public void AddPropsToDict()
{
MyProp = 1;
// Want below to take MyProp by Ref
MyDict.Add("propID", MyProp);
}

public void UpdateValues()
{
MyDict["propID"] = 3;
// Below Prints 3
Console.WriteLine(MyDict["propID"]);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyProp);

/*
// Alternative way does not work either
object oProp = MyDict["propID"];
oProp = 3
// Below Prints 3
Console.WriteLine(oProp);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyDict["propID"]);
// Below Prints 1....Want it to Print 3
Console.WriteLine(MyProp);
*/
}

Thanks!

Hi,

without knowing more details about what you want to achieve I can think
of 3 different approaches.

1) If your dictionary is used inside your class, you can store your
values inside the dictionary and let the property access the values of
the dictionary:

class Test1
{
private IDictionary<string, object> myDict =
new Dictionary<string, object>();
public int MyProp
{
get
{
object o = MyDict["propID"];
if(o == null)
{
o = -1;
MyDict.Add("propID", o);
}
return (int)o;
}
set{ MyDict["propID"] = value; }
}

private IDictionary<string, object> MyDict
{
get { return myDict; }
}

public void UpdateValues()
{
MyDict["propID"] = 3;

Debug.Assert(MyProp == 3);

}
}

// ... Usage
Test1 t1 = new Test1();
t1.UpdateValues();

2) Use Reflection to access the properties in the same manner as a
function pointer map in C/C++:

class Test2
{
private IDictionary<string, PropertyInfo> myDict =
new Dictionary<string, PropertyInfo>();
private int prop = -1;
public int MyProp
{
get { return prop; }
set { prop = value; }
}

private IDictionary<string, PropertyInfo> MyDict
{
get { return myDict; }
}

public void AddPropsToDict()
{
MyProp = 1;

MyDict.Add("propID", GetType().GetProperty("MyProp"));
}

public void UpdateValues()
{
MyDict["propID"].SetValue(this, 3, null);;

Debug.Assert(MyProp == 3);

}
}

// ... Usage
Test2 t2 = new Test2();
t2.AddPropsToDict();
t2.UpdateValues();

3) Build a reference type integer that (almost) behaves like a normal
integer. By almost I mean that this class behaves like a primitive, but
is *not* immutable. This might be error prone, so if possible I would
recomend to hide it from the public interface.

class Integer
{
public Integer(int val)
{
IntValue = val;
}
private int val;
public static implicit operator int(Integer intRef)
{ return intRef.IntValue; }
public static implicit operator Integer(int i)
{ return new Integer(i); }
public static bool operator==(Integer lhs, Integer rhs)
{ return Equals(lhs, rhs); }
public static bool operator !=(Integer lhs, Integer rhs)
{return !Equals(lhs, rhs); }

internal int IntValue// This one is smells.
{
get { return val; }
set { val = value; }
}

public override bool Equals(object o)
{
if(o is int)
return val == (int) o;

Integer rhs = o as Integer;
return rhs != null
? IntValue.Equals(rhs.IntValue)
: false;
}
public override int GetHashCode()
{ return IntValue.GetHashCode(); }
}

class Test3
{
private IDictionary<string, object> myDict = new
Dictionary<string, object>();
private Integer prop = -1;
public Integer MyProp
{
get { return prop; }
set { prop = value; }
}

private IDictionary<string, object> MyDict
{
get { return myDict; }
}

public void AddPropsToDict()
{
MyProp = 1;

MyDict.Add("propID", MyProp);
}

public void UpdateValues()
{
((Integer)MyDict["propID"]).IntValue = 3;

Debug.Assert(MyProp == 3);

}
}

Test3 t3 = new Test3();
t3.AddPropsToDict();
t3.UpdateValues();

HTH,
Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top