代码之家  ›  专栏  ›  技术社区  ›  Nerdynosaur

C#存储和输出字符串列表的最佳方式

  •  1
  • Nerdynosaur  · 技术社区  · 7 年前

    工作包:

    <TextBox Text="{Binding StatusMessage}" TextWrapping="Wrap" AcceptsReturn="True" />
    

    private void OutputMessage(string msg)
    {
        //Result
        //1000  Lines     108ms
        //10000 Lines    1687ms
        if(!string.IsNullOrEmpty(msg))
        {
            string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
    
            int msgLine = 0;
            if (!string.IsNullOrEmpty(StatusMessage))
            {
                //Only show 500 lines of latest messages...
                msgLine = StatusMessage.Count(m => m == '\n');
                if (msgLine > 500)
                    StatusMessage = StatusMessage.Remove(0, StatusMessage.IndexOf("\n") + 1);
    
                StatusMessage = StatusMessage + "\n" + msgWithTimeStamp;
            }
            else
                StatusMessage = msgWithTimeStamp;
        }
    }
    

    方法2(更好的性能):

    List<string> msgList;
    private void OutputMessage(string msg)
    {
        //Result
        //1000  Lines     31ms
        //10000 Lines    377ms
        if (!string.IsNullOrEmpty(msg))
        {
            string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
            msgList.Add(msgWithTimeStamp);
    
            if (msgList.Count > 500)
                msgList.RemoveAt(0);
    
            StatusMessage = String.Join("\n", msgList);
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  4
  •   Phil Wright    7 年前

        2
  •  3
  •   ajawad987    7 年前

    最大的问题是:

    StatusMessage = String.Join("\n", msgList);
    

    这意味着每次更新字符串的主列表时,您都要重新生成整个字符串,并在整个列表中循环,分配新的内存缓冲区,直到缓冲区足够大以填充整个字符串(全部500行)。当消息列表增加到500行时,意味着下一条消息将导致500个缓冲区分配,以便重新生成完整的字符串。

    更好的方法是保持 StringBuilder 在您的邮件列表旁边(在您的 msgList 变量)。 字符串拼接

    我写了下面的代码片段,在我的机器上,向已经有500条消息的列表中添加一条新消息所需的时间不到一毫秒。

    // Somewhere in your code, probably next to your [msgList] variable...
    private StringBuilder sb = new StringBuilder();
    
    private void OutputMessage(string msg)
    {
        if (!string.IsNullOrEmpty(msg))
        {
            string msgWithTimeStamp = System.DateTime.Now.ToString() + ": \t" + msg;
            msgList.Add(msgWithTimeStamp);
            sb.AppendLine(msgWithTimeStamp);
    
            if (msgList.Count > 500)
            {
                sb.Remove(0, msgList[0].Length + 2); // The +2 is to account for the new line and carriage return characters.
                msgList.RemoveAt(0);
            }
    
            statusMessage = sb.ToString();
        }
    }