C# – Replacing a Regex Match Collection in C#

c++performanceregexreplace

I need to find in a text everything that starts with [ and ends with ] and replace it with the value that a function returns. So, here is an example of what I'm doing:

    public string ProcessTemplate(string input)
    {
        return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match)
            {
                return ProcessBlock(match.Result("$1"));
            }));
    }

    public string ProcessBlock(string value)
    {
        return Block.FromString(value).Process();
    }

Now, my problem is when I need to edit blocks. So I thought to find blocks, edit them, and then replacing them in the text.

So, I created a List of blocks, and separated the ProcessTemplate method to two methods: FindBlocks and ReplaceBlocks:

    public void FindBlocks(string input)
    {
        Input = input;

        foreach (Match match in Regex.Matches(input, @"\[(.*?)\]"))
            Blocks.Add(Block.FromString(match.Result("$1")));
    }

    public string ReplaceBlocks()
    {
        string input = Input;

        foreach (Block block in Blocks)
            input = input.Replace("[" + block.OrginalText + "]", block.Process);

        return input;
    }

    public IList<Block> Blocks
    {
        get;
        set;
    }

    public string Input
    {
        get;
        set;
    }

It's working, but the problem is that it is pretty slow. I measured with System.Diagnostics.Stopwatch every part, and I found out that the String.Replace in the ReplaceBlocks method is pretty slow.

How can I improve it?

Thanks.

Best Solution

replacing the string in ReplaceBlock with a StringBuilder may provide a performance increase as every time you perform a string.replace it will have to deallocate the string and reallocate the string. string builder doesnt need to do this.

Replace the contents of the ReplaceBlock with the following.

// This will require a reference to System.Text
StringBuilder input =new StringBuilder(Input);
  foreach (Block block in Blocks)
  {
    input = input.Replace("[" + block.OrginalText + "]", block.Process);
  }
  return input.ToString();

I have also found replacing the foreach loops with a for loop which are quicker.