详解C#string.Format性能

 大家使用String.Format需要注意的一下性能问题。

以前的我总是觉得String.Format用起来非常方便,比+号拼接好多了,久而久之就习惯了用String.Format

这种方式去拼接字符串。今天闲来无聊,就具体得了解了一下String.Format。我这里使用的是反编译工具(Reflector),那么现在就一起去探索一下String.Format这个方法吧。

通过反编译工具查看之后,首先进入我们眼前的是如下代码:

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    StringBuilder sb = StringBuilderCache.Acquire(format.Length + (args.Length * 8));
    sb.AppendFormat(provider, format, args);
    return StringBuilderCache.GetStringAndRelease(sb);
}

我们通过上面的代码可以看出,微软是通过StringBuilder来处理的Format,看到这里,我内心默念了一句,我靠,一直在用sting这个类,里面居然封装的StringBuilder,瞬间感觉微软欺骗我纯洁的内心。好了,咱们继续往下走,既然是使用的是StringBuilder,那么问题来了,他的初始化容量是如何得到的呢?
看到微软的代码:
format.Length + (args.Length * 8)

看上面这个计算公式,我们可以得出结论,根据这个数组的个数(args)去乘以8,然后再加上字符的个数(format)
的长度, 来初始化StringBuilder的容量,那么这样是否就可以了呢?性能上面真的可以吗?

那么问题来了,这个数组(args)的个数是乘以8就相当于每一个数组中的元

素的最大长度只能有8位,如果超过了呢?那么StringBuilder就得扩容啦。

那么这里我就建议大家直接使用StringBuilder吧,这样的话就自己设置容量,

这样就可以把性能掌握在自己手中啦!

2、再来看看里面还有啥?
下面还有一句:

sb.AppendFormat(provider, format, args);
那么这句是干什么的呢? 大家也许根据方法名就可以解读啦。追加格式化的意思。那么博主我的好奇心又来了,
他到底是如何格式化字符串的呢?微软到底是如何写的?于是我进入这个方法:
public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    int num = 0;
    int length = format.Length;
    char ch = '\0';
    ICustomFormatter formatter = null;
    if (provider != null)
    {
        formatter = (ICustomFormatter) provider.GetFormat(typeof(ICustomFormatter));
    }
Label_0096:
    while (num < length)
    {
        ch = format[num];
        num++;
        if (ch == '}')
        {
            if ((num < length) && (format[num] == '}'))
            {
                num++;
            }
            else
            {
                FormatError();
            }
        }
        if (ch == '{')
        {
            if ((num < length) && (format[num] == '{'))
            {
                num++;
            }
            else
            {
                num--;
                break;
            }
        }
        this.Append(ch);
    }
    if (num == length)
    {
        return this;
    }
    num++;
    if (((num == length) || ((ch = format[num]) < '0')) || (ch > '9'))
    {
        FormatError();
    }
    int index = 0;
    do
    {
        index = ((index * 10) + ch) - 0x30;
        num++;
        if (num == length)
        {
            FormatError();
        }
        ch = format[num];
    }
    while (((ch >= '0') && (ch <= '9')) && (index < 0xf4240));
    if (index >= args.Length)
    {
        throw new FormatException(Environment.GetResourceString("Format_IndexOutOfRange"));
    }
    while ((num < length) && ((ch = format[num]) == ' '))
    {
        num++;
    }
    bool flag = false;
    int num4 = 0;
    if (ch == ',')
    {
        num++;
        while ((num < length) && (format[num] == ' '))
        {
            num++;
        }
        if (num == length)
        {
            FormatError();
        }
        ch = format[num];
        if (ch == '-')
        {
            flag = true;
            num++;
            if (num == length)
            {
                FormatError();
            }
            ch = format[num];
        }
        if ((ch < '0') || (ch > '9'))
        {
            FormatError();
        }
        do
        {
            num4 = ((num4 * 10) + ch) - 0x30;
            num++;
            if (num == length)
            {
                FormatError();
            }
            ch = format[num];
        }
        while (((ch >= '0') && (ch <= '9')) && (num4 < 0xf4240));
    }
    while ((num < length) && ((ch = format[num]) == ' '))
    {
        num++;
    }
    object arg = args[index];
    StringBuilder builder = null;
    if (ch == ':')
    {
        num++;
        while (true)
        {
            if (num == length)
            {
                FormatError();
            }
            ch = format[num];
            num++;
            switch (ch)
            {
                case '{':
                    if ((num < length) && (format[num] == '{'))
                    {
                        num++;
                    }
                    else
                    {
                        FormatError();
                    }
                    break;

                case '}':
                    if ((num < length) && (format[num] == '}'))
                    {
                        num++;
                    }
                    else
                    {
                        num--;
                        goto Label_0250;
                    }
                    break;
            }
            if (builder == null)
            {
                builder = new StringBuilder();
            }
            builder.Append(ch);
        }
    }
Label_0250:
    if (ch != '}')
    {
        FormatError();
    }
    num++;
    string str = null;
    string str2 = null;
    if (formatter != null)
    {
        if (builder != null)
        {
            str = builder.ToString();
        }
        str2 = formatter.Format(str, arg, provider);
    }
    if (str2 == null)
    {
        IFormattable formattable = arg as IFormattable;
        if (formattable != null)
        {
            if ((str == null) && (builder != null))
            {
                str = builder.ToString();
            }
            str2 = formattable.ToString(str, provider);
        }
        else if (arg != null)
        {
            str2 = arg.ToString();
        }
    }
    if (str2 == null)
    {
        str2 = string.Empty;
    }
    int repeatCount = num4 - str2.Length;


    if (!flag && (repeatCount > 0))
    {
        this.Append(' ', repeatCount);
    }
    this.Append(str2);
    if (flag && (repeatCount > 0))
    {
        this.Append(' ', repeatCount);
    }
    goto Label_0096;
}
我建议大家不管是在工作中还是学习中,尽量用StringBuilder去处理字符串拼接方面的问
题,因为不管是从性能 方面,还是从用法方面,用StringBuilder绝对是一个正确的选择。
看到里面的方法了吧,我进去后又是一句我靠,忍不住来了一句所噶斯捏! 里面的循环和判
大致 就是一些基础 的字符串判断和叠加操作,相信你们只要用心看一定能看懂的,这里就不多
说了。 基本的对 string.Format就讲完了 ,如果大家还有不懂的可以提出来,感谢大家的
观看,谢谢!!!
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(C#)