2011-02-17 70 views
2

我重构一些代码,我写了一个修改词典返回它的方法的方法时,什么是好的做法。这是比使用参数更好的做法吗?我真的不希望在这种情况下创建一个扩展方法,因为它会的方法添加到词典类,这是矫枉过正这是什么用途。请不要指出我不应该使用动态sql,这是目前必须推迟重构的另一个阶段。编写修改了C#集合

private static Dictionary<int, string> 
      FindMatches(Dictionary<int, string> records, 
         string queryFormat, 
         string region, 
         string type, 
         string label) 
{ 
    var query = string.Format(queryFormat, SqlSvrName, SqlDbName, SqlSchemaName, 
                  region, type, label); 
    using (var dr = DataRepository.Provider.ExecuteReader(CommandType.Text, query)) 
    { 
     if (dr != null && !dr.IsClosed) 
     { 
      while (dr.Read()) 
      { 
       var assetID = (int)dr.GetDouble(0); 
       if (!records.ContainsKey(assetID)) 
        records[assetID] = dr.GetString(1); 
      } 
     } 
    } 
    return records; 
} 

编辑:我是有点仓促与我使用术语的上面。我试图在我的代码中明确表示该字典是由该方法修改的。如果方法创建了一个新的字典并通过该参数返回,那么这里的out参数只有意义。更多的上下文是这个方法被多次调用不同的查询字符串,并且字典可能已经包含匹配。

EDIT2:只是为了跟进我删除了记录参数,而不是从FindMatches返回KeyValuePair的列表。我结束了一个List<KeyValuePair<int, string>>我通过转换为词典:

records 
    .GroupBy(rec => rec.Key) 
    .ToDictionary(grp => grp.Key, grp => grp.First().Value); 

回答

9

为什么要你的方法修改现有的字典呢?它似乎并不使用现有的键/值,因此这方法只返回一个新Dictionary<string, int>

private static Dictionary<int, string> 
      FindMatches(string queryFormat, 
         string region, 
         string type, 
         string label) 
{ 
    var records = new Dictionary<int, string>(); 
    var query = string.Format(queryFormat, SqlSvrName, SqlDbName, 
           SqlSchemaName, region, type, label); 
    using (var dr = DataRepository.Provider.ExecuteReader(CommandType.Text, 
                  query)) 
    { 
     if (dr != null && !dr.IsClosed) 
     { 
      while (dr.Read()) 
      { 
       var assetID = (int)dr.GetDouble(0); 
       // If each assetID in the database will be distinct, you 
       // don't need the "if" here, because you know the dictionary 
       // is empty to start with 
       if (!records.ContainsKey(assetID)) 
       { 
        records[assetID] = dr.GetString(1); 
       } 
      } 
     } 
    } 
    return records; 
} 

然后,您可以写一个单独的方法以特定的方式合并两个库 - 或者返回一个新的字典,这是合并两个现有字典的结果。分离两个问题。

2

我相信,在C#中所有复杂对象的引用是通过引用传递。因此,如果您通过方法内的引用来修改字典,则不需要返回它或指定out/ref关键字。它会在方法范围之外被更改。

+4

不,对象不是通过引用传递的。引用是按值传递的。对象本身根本不通过。有很大的不同。见http://pobox.com/~skeet/csharp/parameters.html – 2011-02-17 21:11:04

+0

是的,乔恩是对的。我错过了。将重述。 – Kon 2011-02-17 21:13:48

+0

Kon我想你的观点是,如果我将字典作为参数传递,我可以直接修改字典,而不必将其作为方法调用的结果返回。我明白,但我想明确说明字典是由该方法修改的。 – 2011-02-17 21:45:19

4

既然你不实际使用的方法的解释(除加油吧等),我会从输入参数删除它,就回到它来代替。

如果你要通过字典中为某种原因,我将有一个void返回并重新命名方法,使一个参数确定,很明显,它具有副作用的输入参数 - 例如

void PopulateRecordsWithMatches(Dictionary<int, string> records...) 
-2

既然你修改的地方字典,我认为这是最好做的是明确的把它作为ref参数:

private static void 
      FindMatches(ref Dictionary<int, string> records, 
         string queryFormat, 
         string region, 
         string type, 
         string label) 
{ 
    var query = string.Format(queryFormat, SqlSvrName, SqlDbName, SqlSchemaName, 
                  region, type, label); 
    using (var dr = DataRepository.Provider.ExecuteReader(CommandType.Text, query)) 
    { 
     if (dr != null && !dr.IsClosed) 
     { 
      while (dr.Read()) 
      { 
       var assetID = (int)dr.GetDouble(0); 
       if (!records.ContainsKey(assetID)) 
        records[assetID] = dr.GetString(1); 
      } 
     } 
    } 
} 

返回,或使用它作为一个输出参数都意味着你正在创建一个新的字典,事实并非如此。另一方面,明确地将其作为ref参数明确表明您打算将字典修改为副作用。

0

out参数就意味着你在一个空的字典传递。这没有意义。你可能是指ref参数。

但是,正如Kon已经说过的,你可以修改方法内的对象的内容。