繁体   English   中英

使用 By Ref 和引用类型字典的意外行为

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM