【问题标题】:Should I dispose of manually a Dictionary data structure after I am done using it?我应该在使用完 Dictionary 数据结构后手动处理它吗?
【发布时间】:2022-10-23 20:00:50
【问题描述】:

是否值得努力尝试并积极处置此代码中的Dictionary,还是将其留给托管垃圾收集?

private void LogReprocessTsk(List<ReprocessTsk> reprocessTsks)
{
    foreach (ReprocessTsk reprocessTsk in reprocessTsks)
    {
        Dictionary<string, string> logMessage = new Dictionary<string, string>
        {
            { "Message", "insert into REPROCESS_TSK - parentId changed" },
            { "TSKLOC", reprocessTsk.TSKLOC },
            { "CRS", reprocessTsk.CRS.ToString() },
            { "PROCESSED", reprocessTsk.PROCESSED.ToString() },
            { "OldParentId", reprocessTsk.OldParentId },
            { "NewParentId", reprocessTsk.NewParentId }
        };

        _logger.LogInformation(JsonConvert.SerializeObject(logMessage));
    }
}

【问题讨论】:

  • 过早优化不是一个好主意。你有一个只有字符串的字典。为什么这有关系什么时候垃圾收集发生了吗?您是否因此测量了应用程序中有意义的瓶颈?
  • 这也可能是一个 X/Y 问题,因为您正在为 JSON 序列化它的灵魂目的创建一个字典。您的记录器方法可以不采用复杂的对象吗?
  • 过早优化不是一个好主意——明白了。我会把它留给垃圾收集。我只是想知道,因为在一个紧密的循环中,可能有任意数量的它们。但是,这永远不会导致瓶颈(我认为),因为与今天的内存资源相比,字符串系列的成本微不足道。
  • 您可以在循环之前创建一个字典并调用logMessage.Clear();,而不是每次都重新创建字典。其他解决方案:只需保留相同的字典而不清除它,然后使用logMessage["key"] = "value"; 重新分配条目。这会自动替换任何现有条目并添加新条目。
  • 应该只处理非托管资源,如连接或文件等。GC应该在这里完成它的工作。您应该根据建议进行优化。

标签: c# .net dictionary coding-style dispose


【解决方案1】:

垃圾收集器的工作做得很好,没有理由强制进行过早的垃圾收集。无论如何,字典在每次迭代时都超出了循环的范围,并自动成为垃圾收集的候选对象。

如果在循环之前只声明一个字典并在使用后将其清除,则可以最大限度地减少对象创建的数量。

var logMessage = new Dictionary<string, string>();
foreach (ReprocessTsk reprocessTsk in reprocessTsks) {
    logMessage.Add("Message", "insert into REPROCESS_TSK - parentId changed");
    logMessage.Add("TSKLOC", reprocessTsk.TSKLOC);
    logMessage.Add("CRS", reprocessTsk.CRS.ToString());
    logMessage.Add("PROCESSED", reprocessTsk.PROCESSED.ToString());
    logMessage.Add("OldParentId", reprocessTsk.OldParentId);
    logMessage.Add("NewParentId", reprocessTsk.NewParentId);

    _logger.LogInformation(JsonConvert.SerializeObject(logMessage));
    logMessage.Clear();
}

由于您在每次 foreach 迭代中都使用相同的键,因此另一种可能性是将新值重新分配给相同的字典键。

var logMessage = new Dictionary<string, string>();
foreach (ReprocessTsk reprocessTsk in reprocessTsks) {
    logMessage["Message"] = "insert into REPROCESS_TSK - parentId changed";
    logMessage["TSKLOC"] = reprocessTsk.TSKLOC;
    logMessage["CRS"] = reprocessTsk.CRS.ToString();
    logMessage["PROCESSED"] = reprocessTsk.PROCESSED.ToString();
    logMessage["OldParentId"] = reprocessTsk.OldParentId;
    logMessage["NewParentId"] = reprocessTsk.NewParentId;

    _logger.LogInformation(JsonConvert.SerializeObject(logMessage));
}

请注意,字典索引器会创建不存在的条目并替换现有的条目。请参阅:remarks sectionDictionary&lt;TKey,TValue&gt;.Item[TKey] 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 2022-01-17
    • 2019-05-02
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多