串更换方法的优化

时间:2010-02-26 13:43:05

标签: c# string

任何人都可以帮助我如何优化此方法吗?

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
    VirtualPathData path = base.GetVirtualPath(requestContext, values);

    if (path != null)
    {
        string virtualPath = path.VirtualPath;
        string condition = string.Empty;

        if (virtualPath.Contains("?"))
        {
            condition = virtualPath.Substring(virtualPath.IndexOf("?"));
            virtualPath = virtualPath.Substring(0, virtualPath.IndexOf("?"));
        }

        virtualPath = virtualPath.Replace(@"%C5%BD", "ž");
        virtualPath = virtualPath.Replace(@"%C4%90", "đ");
        virtualPath = virtualPath.Replace(@"%C4%86", "ć");
        virtualPath = virtualPath.Replace(@"%C4%8C", "č");
        virtualPath = virtualPath.Replace(@"%C5%A0", "š");

        virtualPath = virtualPath.ToLower().Replace(",", "-").Replace("%20", "-").Replace("&", "-");
        virtualPath = virtualPath.Replace(@"-amp;", "&");

        while (virtualPath.Contains("--"))
        {
            virtualPath = virtualPath.Replace("--", "-");
        }

        path.VirtualPath = virtualPath + condition;
    }

    return path;
}

2 个答案:

答案 0 :(得分:4)

在此代码中,您正在为字符扫描字符串三次:

if (virtualPath.Contains("?"))
{
   condition = virtualPath.Substring(virtualPath.IndexOf("?"));
   virtualPath = virtualPath.Substring(0, virtualPath.IndexOf("?"));
}

相反,扫描一次并使用结果三次。同时扫描char而不是字符串:

int pos = virtualPath.IndexOf('?');
if (pos != -1) {
   condition = virtualPath.Substring(pos);
   virtualPath = virtualPath.Substring(0, pos);
}

在这里,您使用相同的替代品进行了多次替换:

virtualPath = virtualPath.ToLower().Replace(",", "-").Replace("%20", "-").Replace("&", "-");

相反,您可以使用正则表达式来匹配所有这些:

virtualPath = Regex.Replace(virtualPath.ToLower(), "(,|%20|&)", "-");

(这实际上是否能提供更好的性能必须使用您的一些实际数据进行测试。尽管操作较少,但设置常规表达会有一些开销。)


您正在使用循环来减少字符串:

while (virtualPath.Contains("--"))
{
   virtualPath = virtualPath.Replace("--", "-");
}

相反,您可以使用正则表达式进行单个替换:

virtualPath = Regex.Replace(virtualPath, "-{2,}", "-");

答案 1 :(得分:0)

最明显的第一步是使用StringBuilder而不是String。

String是不可变类型。这意味着一旦创建,它的价值永远不会改变。因此,对于您在方法中进行的每个Replace调用,程序将创建一个全新的String实例来存储结果,这是内存和处理器密集型的。 (我说的比较一点 - 你不会让你的机器最多只调用一次这种方法,但如果你打电话几千次,你肯定会注意到!)

另一方面,StringBuilder是一个用于在内存中操作字符串的类,每次更改字符串时都不必复制/重新创建内存。

因此,朝着正确方向迈出的一大步将是在方法开始时使用它:

            StringBuilder sb = new StringBuilder(path.VirtualPath.ToLower());
            string condition = string.Empty;

            int index = path.VirtualPath.IndexOf("?");

            if (index > -1)
            {
                condition = virtualPath.Substring(pos);
                sb.Remove(0, index);
            }

            sb.Replace(@"%C5%BD", "ž")
                .Replace(@"%C4%90", "đ")
                .Replace(@"%C4%86", "ć")
                .Replace(@"%C4%8C", "č")
                .Replace(@"%C5%A0", "š")
                .Replace(",", "-")
                .Replace("%20", "-")
                .Replace("&", "-")
                .Replace(@"-amp;", "&");
             sb.Append(condition);

请注意我之前也做了.ToLower()因为StringBuilder没有等效的,并且还注意到了sb.Append,这也会阻止大量的重写。

这不是最好的,但它应该是一个很大的改进......

我错过的一件事就是取代“ - ”。 StringBuilder没有“Contains”函数,但您可以使用正则表达式在一次传递中捕获所有内容(而不是需要循环)。

希望能让你开始!