ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

字符串拼接:语言C#(CSharp)

2021-11-03 20:03:25  阅读:282  来源: 互联网

标签:Console string C# --------------------------------- ms 拼接 WriteLine CSharp


今天我们来介绍一下C#语言的字符串花式拼接方式

1. 基本使用

废话少说,我们直接上代码,介绍一下字符串的拼接的方式

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpPrimeNumber
{
    public class StringSplicingDemo
    {
        public void RunDemo()
        {
            Console.WriteLine("---------------------------------基本使用---------------------------------");
            Console.WriteLine("PlusSignString:" + PlusSignString("小蔡同学", "非常帅"));
            Console.WriteLine("StringFormatString:" + StringFormatString("小蔡同学", "非常帅"));
            Console.WriteLine("StringBuilderString:" + StringBuilderString("小蔡同学", "非常帅"));
            Console.WriteLine("StringFormatVS2017:" + StringFormatVS2017("小蔡同学", "非常帅"));

            Console.WriteLine("--------------------------------------------------------------------------");
        }

        /// <summary>
        /// +号运算
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string PlusSignString(string str1,string str2)
        {
            string strReturn = str1 + str2;
            return strReturn;
        }

        /// <summary>
        /// stringFormat拼接字符串
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string StringFormatString(string str1, string str2)
        {
            string strReturn = string.Format("{0}{1}",str1,str2);
            return strReturn;
        }

        /// <summary>
        /// StringBuilder拼接字符串
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string StringBuilderString(string str1, string str2)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(str1);
            stringBuilder.Append(str2);
            return stringBuilder.ToString();
        }

        /// <summary>
        /// VS2017以上提供的字符串拼接
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string StringFormatVS2017(string str1, string str2)
        {
            string strReturn = string.Format($"{str1}{str2}");
            return strReturn;
        }
    }
    
    static void Main(string[] args)
    {
        StringSplicingDemo pStringSplicingDemo = new StringSplicingDemo();
        pStringSplicingDemo.RunDemo();

        Console.ReadKey();
    }

}

在这里插入图片描述

好了,到这里,今天的博客就水到这里了

哈哈哈,各位看客老爷别走,还没有分析完。我们继续说一下以上这几种方式的适用场景。

2. 具体分析

2.1. 算法效率

我们建立几个测试数据,我们将他们拼接,看看效率差距有多大

  • 简单拼接n次,将str1="小菜同学"str2="非常帅",进行一定次数的拼接
  • 复杂拼接n次,将滕王阁序节选拆分后拼接,进行一定次数的拼接

先看结果

---------------------------------1.基本使用---------------------------------
PlusSignString:小蔡同学非常帅
StringFormatString:小蔡同学非常帅
StringBuilderString:小蔡同学非常帅
StringFormatVS2017:小蔡同学非常帅
--------------------------------------------------------------------------
---------------------------------2.算法效率---------------------------------
---------------------------------2.1.简单拼接---------------------------------
---------------------------------2.1.1.简单拼接10000次---------------------------------
PlusSignString:计算10000总共花费1.5047 ms.
StringFormatString:计算10000总共花费3.3441 ms.
StringBuilderString:计算10000总共花费2.7871 ms.
SingletonStringBuilderString:计算10000总共花费2.6882 ms.
StringFormatVS2017:计算10000总共花费1.5376 ms.
--------------------------------------------------------------------------
---------------------------------2.1.2.简单拼接100000次---------------------------------
PlusSignString:计算100000总共花费10.0948 ms.
StringFormatString:计算100000总共花费34.3649 ms.
StringBuilderString:计算100000总共花费16.5996 ms.
SingletonStringBuilderString:计算100000总共花费17.6449 ms.
StringFormatVS2017:计算100000总共花费62.0455 ms.
---------------------------------2.1.2.简单拼接100000次---------------------------------
PlusSignString:计算1000000总共花费117.9943 ms.
StringFormatString:计算1000000总共花费216.8216 ms.
StringBuilderString:计算1000000总共花费170.7078 ms.
SingletonStringBuilderString:计算1000000总共花费103.9131 ms.
StringFormatVS2017:计算1000000总共花费226.8915 ms.
--------------------------------------------------------------------------
--------------------------------------------------------------------------
---------------------------------2.2.复杂拼接---------------------------------
---------------------------------2.2.1.复杂拼接10000次---------------------------------
披绣闼,俯雕甍,山原旷其盈视,川泽纡其骇瞩,闾阎扑地,钟鸣鼎食之家,舸舰弥津,青雀黄龙之舳,云销雨霁,彩彻区明,落霞与孤鹜齐飞,秋水共长天一色,渔舟唱晚,响穷彭蠡之滨,雁阵惊寒,声断衡阳之浦,遥襟甫畅,逸兴遄飞,爽籁发而清风生,纤歌凝而白云遏,睢园绿竹,气凌彭泽之樽,邺水朱华,光照临川之笔,四美具,二难并,穷睇眄于中天,极娱游于暇日,天高地迥,觉宇宙之无穷,兴尽悲来,识盈虚之有数,望长安于日下,目吴会于云间,地势极而南溟深,天柱高而北辰远,关山难越,谁悲失路之人,萍水相逢,尽是他乡之客,怀帝阍而不见,奉宣室以 何年,嗟乎,时运不齐,命途多舛,冯唐易老,李广难封,屈贾谊于长沙,非无圣主,窜梁鸿于海曲,岂乏明时,所赖君子见机,达人知命,老当益壮,宁移白首之心,穷且益坚,不坠青云之志,酌贪泉而觉爽,处涸辙以犹欢,北海虽赊,扶摇可接,东隅已逝,桑榆非晚,孟尝高洁,空余报国之情,阮籍猖狂,岂效穷途之哭。
PlusSignString:计算10000总共花费107.0751 ms.
StringFormatString:计算10000总共花费211.6322 ms.
StringBuilderString:计算10000总共花费24.7743 ms.
SingletonStringBuilderString:计算10000总共花费13.1791 ms.
StringFormatVS2017:计算10000总共花费667.0529 ms.
--------------------------------------------------------------------------
---------------------------------2.2.2.复杂拼接100000次---------------------------------
PlusSignString:计算100000总共花费708.8968 ms.
StringFormatString:计算100000总共花费1498.7978 ms.
StringBuilderString:计算100000总共花费181.1703 ms.
SingletonStringBuilderString:计算100000总共花费103.6469 ms.
StringFormatVS2017:计算100000总共花费4302.9795 ms.
--------------------------------------------------------------------------

其次结论

  • 当简单拼接时,+的方式是最优的
  • 当复杂拼接时,StringBuilder的方式最优
  • 至于string.Format代码的可读性和维护性高一些

再说原因

  • 简单拼接时,StringBuilder生成实例的方式不划算,且需要对对象进行一定操作清理,如使用SingletonStringBuilderString单例StringBuilder
  • 复杂拼接时,则是由于string类型具有不可变性,在底层的存储方式是采用享元的方式存储的,对string字符串的操作(如拼接、Trim()等)都会在内存中产生一个新的字符串对象,在对字符串进行频繁修改的情况下,如在For循环中进行操作等,那么将会频繁的创建新的字符串对象,造成系统的不必要开销,所以这种情况下大家都推荐使用StringBuilder类来对字符串进行操作,那么到底是怎么实现的呢?可以参见下方代码
    /// <summary>
    /// Appends a string to the end of this builder.
    /// </summary>
    /// <param name="value">The string to append.</param>
    public StringBuilder Append(string? value)
    {
        if (value != null)
        {
            // We could have just called AppendHelper here; this is a hand-specialization of that code.
            char[] chunkChars = m_ChunkChars;
            int chunkLength = m_ChunkLength;
            int valueLen = value.Length;

            if (((uint)chunkLength + (uint)valueLen) < (uint)chunkChars.Length) // Use strictly < to avoid issues if count == 0, newIndex == length
            {
                if (valueLen <= 2)
                {
                    if (valueLen > 0)
                    {
                        chunkChars[chunkLength] = value[0];
                    }
                    if (valueLen > 1)
                    {
                        chunkChars[chunkLength + 1] = value[1];
                    }
                }
                else
                {
                    Buffer.Memmove(
                        ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(chunkChars), chunkLength),
                        ref value.GetRawStringData(),
                        (nuint)valueLen);
                }

                m_ChunkLength = chunkLength + valueLen;
            }
            else
            {
                AppendHelper(value);
            }
        }

        return this;
    }

最后贴代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpPrimeNumber
{
    public class StringSplicingDemo
    {
        public void RunDemo()
        {
            Console.WriteLine("---------------------------------1.基本使用---------------------------------");
            Console.WriteLine("PlusSignString:" + PlusSignString("小蔡同学", "非常帅"));
            Console.WriteLine("StringFormatString:" + StringFormatString("小蔡同学", "非常帅"));
            Console.WriteLine("StringBuilderString:" + StringBuilderString("小蔡同学", "非常帅"));
            Console.WriteLine("StringFormatVS2017:" + StringFormatVS2017("小蔡同学", "非常帅"));
            Console.WriteLine("--------------------------------------------------------------------------");


            Console.WriteLine("---------------------------------2.算法效率---------------------------------");
            Console.WriteLine("---------------------------------2.1.简单拼接---------------------------------");
            Console.WriteLine("---------------------------------2.1.1.简单拼接10000次---------------------------------");
            SimpleTogether(10000, PlusSignString);
            SimpleTogether(10000, StringFormatString);
            SimpleTogether(10000, StringBuilderString);
            SimpleTogether(10000, SingletonStringBuilderString);
            SimpleTogether(10000, StringFormatVS2017);
            Console.WriteLine("--------------------------------------------------------------------------");

            Console.WriteLine("---------------------------------2.1.2.简单拼接100000次---------------------------------");
            SimpleTogether(100000, PlusSignString);
            SimpleTogether(100000, StringFormatString);
            SimpleTogether(100000, StringBuilderString);
            SimpleTogether(100000, SingletonStringBuilderString);
            SimpleTogether(100000, StringFormatVS2017);

            Console.WriteLine("---------------------------------2.1.2.简单拼接100000次---------------------------------");
            SimpleTogether(1000000, PlusSignString);
            SimpleTogether(1000000, StringFormatString);
            SimpleTogether(1000000, StringBuilderString);
            SimpleTogether(1000000, SingletonStringBuilderString);
            SimpleTogether(1000000, StringFormatVS2017);
            Console.WriteLine("--------------------------------------------------------------------------");
            Console.WriteLine("--------------------------------------------------------------------------");

            Console.WriteLine("---------------------------------2.2.复杂拼接---------------------------------");
            Console.WriteLine("---------------------------------2.2.1.复杂拼接10000次---------------------------------");

            List<string> listInfo = new List<string>() {"披绣闼","俯雕甍","山原旷其盈视","川泽纡其骇瞩","闾阎扑地","钟鸣鼎食之家","舸舰弥津","青雀黄龙之舳","云销雨霁","彩彻区明","落霞与孤鹜齐飞","秋水共长天一色","渔舟唱晚","响穷彭蠡之滨","雁阵惊寒","声断衡阳之浦",
                "遥襟甫畅","逸兴遄飞","爽籁发而清风生","纤歌凝而白云遏","睢园绿竹","气凌彭泽之樽","邺水朱华","光照临川之笔","四美具","二难并","穷睇眄于中天","极娱游于暇日","天高地迥","觉宇宙之无穷","兴尽悲来","识盈虚之有数","望长安于日下","目吴会于云间","地势极而南溟深","天柱高而北辰远","关山难越","谁悲失路之人","萍水相逢","尽是他乡之客",
                "怀帝阍而不见","奉宣室以何年",
                "嗟乎","时运不齐","命途多舛","冯唐易老","李广难封","屈贾谊于长沙","非无圣主","窜梁鸿于海曲","岂乏明时",
                "所赖君子见机","达人知命","老当益壮","宁移白首之心","穷且益坚","不坠青云之志","酌贪泉而觉爽","处涸辙以犹欢","北海虽赊","扶摇可接","东隅已逝","桑榆非晚","孟尝高洁","空余报国之情","阮籍猖狂","岂效穷途之哭" };

            Console.WriteLine(string.Join(",", listInfo) + "。");

            ComplexTogether(10000, listInfo, PlusSignString);
            ComplexTogether(10000,listInfo, StringFormatString); 
            ComplexTogether(10000, listInfo, StringBuilderString);
            ComplexTogether(10000, listInfo, SingletonStringBuilderString);
            ComplexTogether(10000, listInfo, StringFormatVS2017);
            Console.WriteLine("--------------------------------------------------------------------------");

            Console.WriteLine("---------------------------------2.2.2.复杂拼接100000次---------------------------------");
            ComplexTogether(100000,listInfo, PlusSignString);
            ComplexTogether(100000,listInfo, StringFormatString);
            ComplexTogether(100000,listInfo, StringBuilderString);
            ComplexTogether(100000, listInfo, SingletonStringBuilderString);
            ComplexTogether(100000, listInfo, StringFormatVS2017);
            Console.WriteLine("--------------------------------------------------------------------------");
        }

        StringBuilder SingletonStringBuilder = new StringBuilder();

        #region 复杂字符串拼接代码段
        /// <summary>
        /// 复杂字符串拼接
        /// </summary>
        /// <param name="num"></param>
        /// <param name="list"></param>
        /// <param name="action"></param>
        public void ComplexTogether(int num, List<string> list, Func<List<string>, string> action)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < num; i++)
            {
                action(list);
            }
            sw.Stop();
            TimeSpan ts2 = sw.Elapsed;
            Console.WriteLine($"{action.Method.Name}:计算{num}总共花费{ts2.TotalMilliseconds} ms.");
        }

        public string PlusSignString(List<string> listInfo)
        {
            string strReturn = "";
            for (int i = 0; i < listInfo.Count; i++)
            {
                strReturn += listInfo[i];
            }
            return strReturn;
        }

        public string StringFormatString(List<string> listInfo)
        {
            string strReturn = "";
            for (int i = 0; i < listInfo.Count; i++)
            {
                strReturn =string.Format("{0}{1}",strReturn,listInfo[i]);
            }
            return strReturn;
        }


        public string StringBuilderString(List<string> listInfo)
        {
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var item in listInfo)
            {
                stringBuilder.Append(item);
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// StringBuilder拼接字符串
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string SingletonStringBuilderString(List<string> listInfo)
        {
            SingletonStringBuilder.Clear();
            foreach (var item in listInfo)
            {
                SingletonStringBuilder.Append(item);
            }
            return SingletonStringBuilder.ToString();
        }

        public string StringFormatVS2017(List<string> listInfo)
        {
            string strReturn = "";
            for (int i = 0; i < listInfo.Count; i++)
            {
                strReturn = string.Format($"{strReturn}{listInfo[i]}");
            }
            return strReturn;
        }
        #endregion

        #region 简单字符串拼接代码段
        /// <summary>
        /// 简单字符串拼接
        /// </summary>
        /// <param name="num"></param>
        /// <param name="action"></param>
        public void SimpleTogether(int num, Func<string,string, string> action)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < num; i++)
            {
                action("小蔡同学", "非常帅"+i);
            }
            sw.Stop();
            TimeSpan ts2 = sw.Elapsed;
            Console.WriteLine($"{action.Method.Name}:计算{num}总共花费{ts2.TotalMilliseconds} ms.");
        }

        /// <summary>
        /// +号运算
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string PlusSignString(string str1,string str2)
        {
            string strReturn = str1 + str2;
            return strReturn;
        }

        /// <summary>
        /// stringFormat拼接字符串
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string StringFormatString(string str1, string str2)
        {
            string strReturn = string.Format("{0}{1}",str1,str2);
            return strReturn;
        }

        /// <summary>
        /// StringBuilder拼接字符串
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string SingletonStringBuilderString(string str1, string str2)
        {
            SingletonStringBuilder.Clear();
            SingletonStringBuilder.Append(str1);
            SingletonStringBuilder.Append(str2);
            return SingletonStringBuilder.ToString();
        }

        /// <summary>
        /// StringBuilder拼接字符串
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string StringBuilderString(string str1, string str2)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(str1);
            stringBuilder.Append(str2);
            return stringBuilder.ToString();
        }

        /// <summary>
        /// VS2017以上提供的字符串拼接
        /// </summary>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public string StringFormatVS2017(string str1, string str2)
        {
            string strReturn = string.Format($"{str1}{str2}");
            return strReturn;
        }
        #endregion
    }
}

2.2 代码可读性

  1. 简单情况下+运算,是最清晰的
  2. 极度复杂且重复的情况下StringBuilder是最佳的方式
  3. 当只是拼接一次长字符串是,我认为string.format可读性是最强的
  • string.Format("{0}",str) 和 string.Format($"{str}")

    • string.Format($"{str}") 我非常推崇这种写法

举例说明:现在有一个如下代码,使用string.Format("{0}",str)

string strUpdateSql=string.Format("update {0} set FieldA='{1}' where ID ={2}",TableName,FieldAValuem,IDValue);

以上代码是拼接一个sql语句,这样相较+StringBuilder更加具有优势。

如果这个strUpdateSql不发生改变就还好,但是如果发生改变,如现在需要多更新几个字段,代码转变为如下:几种情况

string strUpdateSql=string.Format("update {0} set FieldA='{1}',FieldA='{2}' where ID ={3}",TableName,FieldAValuem,FieldBValuem,IDValue);
string strUpdateSql=string.Format("update {0} set FieldA='{1}',FieldA='{3}' where ID ={2}",TableName,FieldAValuem,IDValue,FieldBValuem);

如果仔细思考的话,我们应该想到:当字段复杂的时候上述两种拼接都是一个毫无必要的拼接,第一种情况:遵循强迫症或者说为了代码有一个从始至终的编码逻辑,就需要调整,第二种情况:可以预想到当经过几轮的没有原则的修改,这个长代码的维护性及其的差

一下我们贴一下+的代码,仔细对比一下,个人认为在代码的引号上非常容易出错

string strUpdateSql="update "+TableName+" set FieldA='"+FieldAValuem+"',FieldA='"+FieldBValuem+"' where ID ="+IDValue;

在这里我们写一下string.Format($"{str}")

string strUpdateSql=string.Format($"update {TableName} set FieldA='{FieldAValuem}',FieldA='{FieldBValuem}' where ID ={IDValue}");

以上代码的可读性以及维护性及其的好。

但是,凡是都担心但是,这种写法是在VS2017之后出现的,这种写法是编译器行为,如果需要在低版本VS中继续编写代码时,就不建议使用这种代码编写格式了。

3. 小技巧

我个人还是看了蛮多上古代码的,其中有一种代码我见过很多,现在有三个人名,需要用、分隔拼接起来,大部分代码如下方式。


List<string> listName=new List<string>(){"张三","李四","王五"};

string strReturn=listName[0];

for(int i=1;i<listName.Count;i++)
{
    strReturn+="、"+listName[0];
}

// string strReturn="";
// for(int i=0;i<listName.Count;i++)
// {
//     strReturn+="、"+listName[0];
// }
// strRetuern=strReturn==""?strReturn:strReturn.SubString(1);

return strReturn;

个人的写法如下:


List<string> listName=new List<string>(){"张三","李四","王五"};

string strReturn=string.Join("、",listName);

C#源码如下:mscorlib_Source\System\String.cs

[ComVisible(false)]
public static string Join(string separator, IEnumerable<string> values)
{
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }
    if (separator == null)
    {
        separator = Empty;
    }
    using (IEnumerator<string> enumerator = values.GetEnumerator())
    {
        if (!enumerator.MoveNext())
        {
            return Empty;
        }
        StringBuilder builder = new StringBuilder();
        if (enumerator.Current != null)
        {
            builder.Append(enumerator.Current);
        }
        while (enumerator.MoveNext())
        {
            builder.Append(separator);
            if (enumerator.Current != null)
            {
                builder.Append(enumerator.Current);
            }
        }
        return builder.ToString();
    }
}

我个人写代码和改代码都相较蛮快的,是因为在每一个细节上都考虑可读性、简洁、是不是常人思路以及这个地方如果改怎么方便改

标签:Console,string,C#,---------------------------------,ms,拼接,WriteLine,CSharp
来源: https://blog.csdn.net/a13407142317/article/details/121120592

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有