天天看点

使用string.EndsWith方法是别忘了用StringComparison.Ordinal!

今天项目(C#项目)中遇到了一个性能问题,在对一个10万字左右文本解析时速度特别慢,用Profiler调查了一下原来大多时间都用在了String.EndsWith这个方法上。 大家现在看下面一段程序。

var sb = new StringBuilder(100000);
            for (var i = 0; i < 10000; i++)
            {
                sb.Append("ABCDEFGHIJ");
            }
            var text = sb.ToString();
            var sw = new Stopwatch();
            sw.Start();
            for (var i = 0; i < 10000; i++)
            {
                var b = text.EndsWith("AAAA");
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);
      

大家觉得这段程序大概要执行多长时间?

在我的机器上:36782 毫秒

大家再看这段代码

var sb = new StringBuilder(100000);
            for (var i = 0; i < 10000; i++)
            {
                sb.Append("ABCDEFGHIJ");
            }
            var text = sb.ToString();
            var sw = new Stopwatch();
            sw.Start();
            for (var i = 0; i < 10000; i++)
            {
                var b = text.EndsWith("AAAA", StringComparison.Ordinal);
            }
            sw.Stop();
            Console.WriteLine(sw.ElapsedMilliseconds);      

仅仅加了一个StringComparison.Ordinal, 执行时间是0,也就是不到1毫秒。

之前一直做java的项目,对于java里的String的endsWith出了比较字符串以外没有任何悬念。所以习惯性的在C#里也这样用。 但是在C#里,StringComparison.Ordinal才是常规用法。因为:

1. 用了它EndsWith会非常快

2. 一般情况下就是你想要的比较方式

使用StringComparison.Ordinal的比较方式就是我们常用的把字符当纯数字的比较方式。

如果不加这个参数, String的EndsWith的比较方式是culture-sensitive的,相当于EndsWith(str, StringComparison.CurrentCulture)。 这个是什么概念呢。 简单来讲就是某些语言上,虽然字符不同但是在语言上是相同的。

例如在德语环境下:

static void Main(string[] args)
{
  Console.WriteLine("Grüße".EndsWith("sse", StringComparison.Ordinal));
  Console.WriteLine("Grüße".EndsWith("sse", StringComparison.CurrentCulture));
  Console.WriteLine("Grüße".EndsWith("sse", StringComparison.InvariantCulture));
  Console.WriteLine("Grüße".EndsWith("sse"));
}      

得到的结果是:

False
True
True
True