编写修改c#集合的方法时,有什么好的做法

时间:2011-02-17 21:05:23

标签: c# coding-style

我正在重构一些代码,我编写了一个修改 Dictionary 并返回它的方法。这比使用 out 参数更好吗?在这种情况下,我真的不想创建一个扩展方法,因为它会将方法添加到 Dictionary 类中,这对于它的用途来说是过度的。请不要指出我不应该使用动态sql,这是目前必须推迟的重构中的另一个阶段。

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 一词感到有些仓促。我试图在我的代码中明确表示该方法修改了字典。这里的out参数只有在方法创建了一个新字典并通过该参数返回时才有意义。为此更多的上下文是使用不同的查询字符串多次调用该方法,并且字典可能已经包含匹配。

Edit2:为了跟进,我删除了记录参数,而是从 FindMatches 返回 KeyValuePair 的列表。我最终得到了List<KeyValuePair<int, string>>,我通过以下方式转换为字典:

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

5 个答案:

答案 0 :(得分: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;
}

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

答案 1 :(得分:4)

由于你实际上并没有在方法中使用Dictionary(除了填充它),我会从输入参数中删除它而只是返回它。

如果由于某种原因你必须将字典作为参数传递,我会有一个void返回并重命名该方法,以确保它对输入参数有明显的副作用 - 例如

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

答案 2 :(得分:2)

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

答案 3 :(得分:0)

out参数意味着您传入一个空字典。这没有意义。您可能需要ref参数。

但正如Kon所说,你可以修改方法内对象的内容。

答案 4 :(得分:-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);
            }
        }
    }
}

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