在C#中存储对对象的引用
本文关键字:对象 引用 存储 | 更新日期: 2023-09-27 17:50:28
我目前正在C#中编写一个VariableWatcher
类
我想做的是,每次变量更改为特定值时都引发一个事件
例如:我有一个bool a
,它是false。我将它与应该引发事件的值true
一起传递给VariableWatcher类
我已经找到了解决这个问题的方法,但我显然误解了关于装箱/拆箱的一些观点
这是我的代码:
public class ValueWatch
{
public delegate void ValueTriggeredD(string ID, string valuename, object source);
public event ValueTriggeredD ValueTriggered;
Dictionary<string, object[]> LookUp = new Dictionary<string, object[]>(); //Key = ID, Value[0] = PropertyName, Value[1] = ObjTrigger, Value[2] = ObjWatch
Timer ttt;
public void Initialize()
{
ttt = new Timer(new TimerCallback(CB_T), null, 0, 50);
}
void CB_T(object o)
{
if (LookUp.Count > 0)
{
foreach (KeyValuePair<string, object[]> kvp in LookUp)
{
Type tp = kvp.Value[2].GetType();
FieldInfo inf = tp.GetField((string)kvp.Value[0]);
if (inf != null)
{
object curval = inf.GetValue(kvp.Value[2]);
if (curval == kvp.Value[1])
{
if (ValueTriggered != null)
ValueTriggered(kvp.Key, (string)kvp.Value[0], kvp.Value[2]);
}
}
}
}
}
public void StartWatching(string ID, object ListObj, object ValueForTrigger, string PropertyName)
{
if (LookUp.ContainsKey(ID))
System.Diagnostics.Debug.Print("already there");
else
{
LookUp.Add(ID, new object[] { PropertyName, ValueForTrigger, ListObj });
}
}
public void StopWatching(string ID)
{
LookUp.Remove(ID);
}
}
我的问题是:为什么当我更改Value[2]中存储的对象时,它不会更改?
示例:
bool b = false;
valueWatch.ValueTriggered += new ValueTriggeredD(this.VT);
valueWatch.StartWatching("ID1", this, true, "b");
...
b = true;
...
void VT(string ID, string VN, object Source)
{
//Never triggered
}
没错。它永远不会触发。当你对有价值的类型进行装箱时,你实际上会复制一个值并将其放入内存。所以,当您更改变量的值时,并没有更改装箱的值。首先想到的是使用不安全的上下文对变量地址进行装箱,但不幸的是。NET不支持指针装箱(来自MSDN(:
指针类型不从对象继承,指针类型和对象之间也不存在转换。此外,装箱和取消装箱不支持指针。但是,您可以在不同的指针类型之间转换,也可以在指针类型和积分类型之间转换。
因此,唯一可能的方法是使用不安全的上下文并将所有变量的地址存储在void*
中,如下所示:
unsafe
{
bool test = false;
bool* adr = &test;
void* testObj = adr;
test = true;
Console.WriteLine("native test's value is" + test.ToString());
Console.WriteLine("unboxed test's value is" + (*((bool*)testObj)).ToString());
}
但正如它在评论中提到的,为什么不实现当属性发生更改时会触发的事件呢?
我终于明白了:
我将Value[2]设置为对象的WeakReference
,而不是将其设置为对象副本
然后我只需要从WeakReference中获取值,就有了我的对象。。。