Regex to first match, then replace found matches
Regex.Matches returns a MatchCollection which contains Matches which captures the index and length of each match. So as such you won't have to fire up the regex engine again because you can do something like this:

string toSearchInside; // The actual string I'm going to be replacing within
List&lt;string&gt; searchStrings; // The list of words to look for via regex

string pattern = @"([:@?]{0})";
string replacement;

foreach (string toMatch in searchStrings)
{
    var regex = new Regex(
                            string.Format(pattern, toMatch), 
                            RegexOptions.IgnoreCase
                            );
    var matches = regex.Matches(toSearchInside);

    if (matches.Count == 0)
        continue;

    replacement = CreateReplacement(toMatch);

    // in case the replacement is of a different length we replace from
    // from back to front to keep the match indices correct
    foreach (var match in matches.Cast&lt;Match&gt;().Reverse())
    {
        toSearchInside = toSearchInside.Replace(match.Index, match.Length, replacement);
    }
}


Unfortunately the .NET framework doesn't come with a positional Replace so we have to create one which I did as an extension method:

public static string Replace(this string s, int index, int length, string replacement)
{
    var builder = new StringBuilder();
    builder.Append(s.Substring(0,index));
    builder.Append(replacement);
    builder.Append(s.Substring(index + length));
    return builder.ToString();
}


If you do this often and the match patterns don't change you could consider two things:


Pre-compile the regular expressions
Pre-create the replacements