今天我们来介绍一下C#语言的字符串花式拼接方式
废话少说,我们直接上代码,介绍一下字符串的拼接的方式
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(); } }
好了,到这里,今天的博客就水到这里了
哈哈哈,各位看客老爷别走,还没有分析完。我们继续说一下以上这几种方式的适用场景。
我们建立几个测试数据,我们将他们拼接,看看效率差距有多大
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 } }
+
运算,是最清晰的StringBuilder
是最佳的方式长字符串是
,我认为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中继续编写代码时,就不建议使用这种代码编写格式了。
我个人还是看了蛮多上古代码
的,其中有一种代码我见过很多,现在有三个人名,需要用、分隔拼接起来
,大部分代码如下方式。
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(); } }
我个人写代码和改代码都相较蛮快的,是因为在每一个细节上都考虑可读性、简洁、是不是常人思路以及这个地方如果改怎么方便改