[英]Unexpected behavior using By Ref with Reference type Dictionary
使用字典类型并按引用传递时遇到意外行为。 在嵌套调用中,对底层基础字典的引用似乎丢失或被替换。 所有子方法调用都通过 ref 传递字典。
public void Main() {
// Get Dictionary and fill if empty - Type 1 Dictionary
Dictionary<string, string> dictStored = DictControllerMethod(1);
// Pull from previously filled and stored static dictionary
dictStored = DictControllerMethod(1);
}
我的理解是我正在传递本地类型的地址引用(它本身是引用类型 object - 字典)。
如果在父字典上发生操作的子方法上分配了字典(意味着它是相同的 object,相同的 memory 地址引用)。
在DictControllerMethod()
中,不需要将本地字典的最终 switch..case 分配给 static 字典。 在经典的 C++ 中,对根 dictA/dictB object 和 localDict 的引用是相同的。
// Method to find and return the correct Dictionary by Type.
void DictControllerMethod(int DictType)
{
Dictionary<string, string> localDict = new();
// Retrieve Dict pass by reference
// localDict will contain static dictA or dictB contents
DictFetchStaticMethod(dictType, ref localDict);
// Check dict, fill if empty
if (localDict.Count == 0)
{
// Method to fill localDict with entries.
FillDictMethod(ref localDict);
// Here is the gotcha, the static dictA or dictB is still empty,
// localDict is populated,
switch(dictType)
{
case 1:
dictA = localDict;
break;
case 2:
dictB = localDict;
break;
};
}
return localDict;
}
我错过了什么? 为什么在DictControllerMethod()
的最终 switch..case 语句之前没有填充 dictA?
static Dictionary<string, string> dictA = new();
static Dictionary<string, string> dictB = new();
void DictFetchStaticMethod(int dictType, ref Dictionary<string, string> dictRequester)
{
switch(dictType)
{
case 1:
dictRequester = dictA;
break;
case 2:
dictRequester = dictB;
break;
};
}
void FillDictMethod(ref Dictionary<string, string> dictRequester)
{
// Just an example of filling a dictionary using DbContext, its generating a new Dict in response.
dictRequester = _context.owner.Where(x => x.type == 'abc')
.ToDictionary(o => o.key, o => o.value);
}
您正在FillDictMethod
中分配一个新的引用(地址)。 您的参考将不再指向dictA
。
如果您希望它按预期工作,您需要改变ref
变量,而不仅仅是将其重新分配到其他地方。
static void FillDictMethod( ref Dictionary<string, string> dictRequester )
{
// Add the values to the dictionary pointed to
// by dictRequester.
dictRequester.TryAdd( "Test", "Test" );
}
感谢有用的回复提示。 在我的真实场景中,填充方法将使用 DbContext 并将生成一个新的非常大的字典。
解决方案是避免使用本地 scope 定义的字典 var,而是在 DictControllerMethod() 中定义一个ref 字典。 这避免了我的问题中报告的 [pointer to a pointer] 问题 - 只需使用并传递一个指向根字典的指针。
它使用本地定义的字典变量,导致不必要的附加层。 按值使用引用类型[字典]增加了混乱。
static Dictionary<string, string> dictA = new();
static Dictionary<string, string> dictB = new();
ref Dictionary<string, string> DictFetchStaticMethod()
{
switch(dictType)
{
case 1:
return dictA;
case 2:
return dictB;
};
}
// Method to find and return the correct Dictionary by Type.
void DictControllerMethod(int DictType)
{
// localDict will point to static dictA or dictB Dictionary reference type.
ref Dictionary<string, string> localDict = ref DictFetchStaticMethod();
// Check dict, fill if empty
if (localDict.Count == 0)
{
// Method to fill localDict with entries.
FillDictMethod(ref localDict);
// Here is the gotcha, the static dictA or dictB is still empty,
// localDict is populated,
switch(dictType)
{
case 1:
dictA = localDict;
break;
case 2:
dictB = localDict;
break;
};
}
return localDict;
}
void FillDictMethod(ref Dictionary<string, string> dictRequester)
{
// Just an example of filling a dictionary using DbContext, its generating a new Dict in response.
dictRequester = _context.owner.Where(x => x.type == 'abc')
.ToDictionary(o => o.key, o => o.value);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.