String splicing: language C# (CSharp)

Today, let's introduce the fancy string splicing method of C# language

1. Basic use

Less nonsense, let's go directly to the code and introduce the splicing method of strings

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("---------------------------------Basic use---------------------------------");
            Console.WriteLine("PlusSignString:" + PlusSignString("Xiao Cai", "Very handsome"));
            Console.WriteLine("StringFormatString:" + StringFormatString("Xiao Cai", "Very handsome"));
            Console.WriteLine("StringBuilderString:" + StringBuilderString("Xiao Cai", "Very handsome"));
            Console.WriteLine("StringFormatVS2017:" + StringFormatVS2017("Xiao Cai", "Very handsome"));

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

        /// <summary>
        ///+ sign operation
        /// </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 splice string
        /// </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 splicing string
        /// </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 string splicing provided above
        /// </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();
    }

}

Well, that's it. Today's blog is here

Hahaha, please don't go. I haven't finished the analysis yet. Let's continue to talk about the applicable scenarios of the above methods.

2. Specific analysis

2.1. Algorithm efficiency

We build several test data, and we splice them to see how big the efficiency gap is

  • Simply splice n times, and splice str1 = "classmate" and str2 = "very handsome" for a certain number of times
  • For complex splicing n times, the sequence excerpts of tengwangge are split and spliced for a certain number of times

Look at the results first

---------------------------------1.Basic use---------------------------------
PlusSignString:Xiao Cai is very handsome
StringFormatString:Xiao Cai is very handsome
StringBuilderString:Xiao Cai is very handsome
StringFormatVS2017:Xiao Cai is very handsome
--------------------------------------------------------------------------
---------------------------------2.Algorithm efficiency---------------------------------
---------------------------------2.1.Simple splicing---------------------------------
---------------------------------2.1.1.Simple splicing 10000 times---------------------------------
PlusSignString:Calculating 10000 costs 1 in total.5047 ms.
StringFormatString:Calculating 10000 costs 3 in total.3441 ms.
StringBuilderString:Calculating 10000 costs 2 in total.7871 ms.
SingletonStringBuilderString:Calculating 10000 costs 2 in total.6882 ms.
StringFormatVS2017:Calculating 10000 costs 1 in total.5376 ms.
--------------------------------------------------------------------------
---------------------------------2.1.2.Simple splicing 100000 times---------------------------------
PlusSignString:Calculating 100000 costs a total of 10.0948 ms.
StringFormatString:Calculating 100000 costs a total of 34.3649 ms.
StringBuilderString:Calculating 100000 costs a total of 16.5996 ms.
SingletonStringBuilderString:Calculating 100000 costs a total of 17.6449 ms.
StringFormatVS2017:The total cost of calculating 100000 is 62.0455 ms.
---------------------------------2.1.2.Simple splicing 100000 times---------------------------------
PlusSignString:The total cost of calculating 1000000 is 117.9943 ms.
StringFormatString:The total cost of calculating 1000000 is 216.8216 ms.
StringBuilderString:The total cost of calculating 1000000 is 170.7078 ms.
SingletonStringBuilderString:Calculate 1000000 total cost 103.9131 ms.
StringFormatVS2017:Calculation of 1000000 total cost 226.8915 ms.
--------------------------------------------------------------------------
--------------------------------------------------------------------------
---------------------------------2.2.Complex splicing---------------------------------
---------------------------------2.2.1.10000 times of complex splicing---------------------------------
Phi embroidery,Overhanging carving,Yamahara is open and full of vision,Chuan Ze Yu's astonishing attention,prosperou,a stately house,Ge jianmizin,Green sparrow and yellow dragon start,Cloud selling rain Ji,Cai Che Qu Ming,The evening glow parallels with a lonely duck to fly,The autumn river shares a scenic hue with the vast sky,Fishing boat singing night,Sound poor Peng Li's shore,Wild geese startle cold,Sound breaks the river of Hengyang,Yao Jiefu Chang,in high and vigorous spirits,Cool sound and fresh wind,Fine songs condense and white clouds suppress,Suiyuan green bamboo,Qi Ling Peng Ze's bottle,Ye Shui Zhu Hua,Light Linchuan's pen,Si Meiju,Two difficult combinations,Poor look at the sky,Extremely entertaining in the summer,very high,Feel the infinity of the universe,Be happy and sad,Know the number of surplus and deficiency,I hope Chang'an is in the sun,Wu meets in the clouds,The terrain is extremely deep in the south,The Tianzhu is high and the Beichen is far away,Guan Shan is difficult to cross,Who is the one who has lost his way,meet by chance like patches of drifting duckweed,It's full of foreign guests,Huai Di is missing,What is the year of Fengxuan office,Oh,down on the luck,suffer many a setback during one 's life,be born under an unlucky star,talented but unrecognized,Qu Jiayi in Changsha,Not without God,Channeling Liang Hong Yu Haiqu,Is there a lack of time,The gentleman depends on the opportunity,aware that all things depend upon the will of god,old but vigorous,Rather move the heart of white head,poor and stronger,Don't fall into the blue cloud,Drink the spring and feel cool,A dry rut makes you happy,Beihai is on credit,Whirlwind can be connected,The east corner is dead,Sang Yufei,Meng tasted Gaojie,Spare time to serve the country,Ruan Ji is rampant,It is useless to cry at the end of the road.
PlusSignString:Calculating 10000 costs 107 in total.0751 ms.
StringFormatString:The total cost of calculating 10000 is 211.6322 ms.
StringBuilderString:Calculating 10000 costs 24 in total.7743 ms.
SingletonStringBuilderString:Calculating 10000 costs 13 in total.1791 ms.
StringFormatVS2017:Calculating 10000 costs 667 in total.0529 ms.
--------------------------------------------------------------------------
---------------------------------2.2.2.100000 times of complex splicing---------------------------------
PlusSignString:The total cost of calculating 100000 is 708.8968 ms.
StringFormatString:Calculating 100000 costs 1498 in total.7978 ms.
StringBuilderString:Calculating 100000 costs 181 in total.1703 ms.
SingletonStringBuilderString:Calculating 100000 costs a total of 103.6469 ms.
StringFormatVS2017:The total cost of calculating 100000 is 4302.9795 ms.
--------------------------------------------------------------------------

Second conclusion

  • When simple splicing, the + method is the best
  • When complex splicing, StringBuilder works best
  • As for string.Format, the code is more readable and maintainable

Again, why

  • During simple splicing, the method of generating instances by StringBuilder is not cost-effective, and the objects need to be cleaned up, such as using singleton StringBuilder string singleton StringBuilder
  • In complex splicing, because the string type is immutable, the underlying storage method is shared. The operation of string (such as splicing, Trim(), etc.) will generate a new string object in memory. In the case of frequent modification of string, such as operation in For loop, etc, Then new string objects will be created frequently, resulting in unnecessary overhead of the system. Therefore, in this case, it is recommended to use StringBuilder class to operate strings. How is it implemented? See code below
    /// <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;
    }

Last post code

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.Basic use---------------------------------");
            Console.WriteLine("PlusSignString:" + PlusSignString("Xiao Cai", "Very handsome"));
            Console.WriteLine("StringFormatString:" + StringFormatString("Xiao Cai", "Very handsome"));
            Console.WriteLine("StringBuilderString:" + StringBuilderString("Xiao Cai", "Very handsome"));
            Console.WriteLine("StringFormatVS2017:" + StringFormatVS2017("Xiao Cai", "Very handsome"));
            Console.WriteLine("--------------------------------------------------------------------------");


            Console.WriteLine("---------------------------------2.Algorithm efficiency---------------------------------");
            Console.WriteLine("---------------------------------2.1.Simple splicing---------------------------------");
            Console.WriteLine("---------------------------------2.1.1.Simple splicing 10000 times---------------------------------");
            SimpleTogether(10000, PlusSignString);
            SimpleTogether(10000, StringFormatString);
            SimpleTogether(10000, StringBuilderString);
            SimpleTogether(10000, SingletonStringBuilderString);
            SimpleTogether(10000, StringFormatVS2017);
            Console.WriteLine("--------------------------------------------------------------------------");

            Console.WriteLine("---------------------------------2.1.2.Simple splicing 100000 times---------------------------------");
            SimpleTogether(100000, PlusSignString);
            SimpleTogether(100000, StringFormatString);
            SimpleTogether(100000, StringBuilderString);
            SimpleTogether(100000, SingletonStringBuilderString);
            SimpleTogether(100000, StringFormatVS2017);

            Console.WriteLine("---------------------------------2.1.2.Simple splicing 100000 times---------------------------------");
            SimpleTogether(1000000, PlusSignString);
            SimpleTogether(1000000, StringFormatString);
            SimpleTogether(1000000, StringBuilderString);
            SimpleTogether(1000000, SingletonStringBuilderString);
            SimpleTogether(1000000, StringFormatVS2017);
            Console.WriteLine("--------------------------------------------------------------------------");
            Console.WriteLine("--------------------------------------------------------------------------");

            Console.WriteLine("---------------------------------2.2.Complex splicing---------------------------------");
            Console.WriteLine("---------------------------------2.2.1.10000 times of complex splicing---------------------------------");

            List<string> listInfo = new List<string>() {"Phi embroidery","Overhanging carving","Yamahara is open and full of vision","Chuan Ze Yu's astonishing attention","prosperou","a stately house","Ge jianmizin","Green sparrow and yellow dragon start","Cloud selling rain Ji","Cai Che Qu Ming","The evening glow parallels with a lonely duck to fly","The autumn river shares a scenic hue with the vast sky","Fishing boat singing night","Sound poor Peng Li's shore","Wild geese startle cold","Sound breaks the river of Hengyang",
                "Yao Jiefu Chang","in high and vigorous spirits","Cool sound and fresh wind","Fine songs condense and white clouds suppress","Suiyuan green bamboo","Qi Ling Peng Ze's bottle","Ye Shui Zhu Hua","Light Linchuan's pen","Si Meiju","Two difficult combinations","Poor look at the sky","Extremely entertaining in the summer","very high","Feel the infinity of the universe","Be happy and sad","Know the number of surplus and deficiency","I hope Chang'an is in the sun","Wu meets in the clouds","The terrain is extremely deep in the south","The Tianzhu is high and the Beichen is far away","Guan Shan is difficult to cross","Who is the one who has lost his way","meet by chance like patches of drifting duckweed","It's full of foreign guests",
                "Huai Di is missing","What is the year of Fengxuan office",
                "Oh","down on the luck","suffer many a setback during one 's life","be born under an unlucky star","talented but unrecognized","Qu Jiayi in Changsha","Not without God","Channeling Liang Hong Yu Haiqu","Is there a lack of time",
                "The gentleman depends on the opportunity","aware that all things depend upon the will of god","old but vigorous","Rather move the heart of white head","poor and stronger","Don't fall into the blue cloud","Drink the spring and feel cool","A dry rut makes you happy","Beihai is on credit","Whirlwind can be connected","The east corner is dead","Sang Yufei","Meng tasted Gaojie","Spare time to serve the country","Ruan Ji is rampant","How can you cry at the end" };

            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 times of complex splicing---------------------------------");
            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 complex string splicing code snippet
        /// <summary>
        ///Complex string splicing
        /// </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}:calculation{num}Total cost{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 splicing string
        /// </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 simple string splicing code snippet
        /// <summary>
        ///Simple string splicing
        /// </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("Xiao Cai", "Very handsome"+i);
            }
            sw.Stop();
            TimeSpan ts2 = sw.Elapsed;
            Console.WriteLine($"{action.Method.Name}:calculation{num}Total cost{ts2.TotalMilliseconds} ms.");
        }

        /// <summary>
        ///+ sign operation
        /// </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 splice string
        /// </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 splicing string
        /// </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 splicing string
        /// </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 string splicing provided above
        /// </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 code readability

  1. In simple cases, the + operation is the clearest
  2. StringBuilder is the best way in extremely complex and repetitive situations
  3. When you just splice a long string once, I think string.format is the most readable
  • string.Format("{0}",str) and string.Format($"{str}")

    • string.Format($"{str}") I highly recommend this way of writing

For example: now there is a following code, using string.Format("{0}",str)

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

The above code is to splice an sql statement, which has more advantages than + and StringBuilder.

It's ok if the strUpdateSql doesn't change, but if it changes, for example, you need to update several more fields now, the code changes to the following situations:

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);

If we think about it carefully, we should think that when the fields are complex, the above two splicing are unnecessary. The first case: it needs to be adjusted to follow obsessive-compulsive disorder or to have a coding logic from beginning to end. The second case: it can be expected that the maintainability of this long code will be poor after several rounds of unprincipled modifications

Let's paste the code of + and compare it carefully. Personally, I think it's very easy to make mistakes in the quotation marks of the code

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

Here, let's write string.Format($"{str}")

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

The readability and maintainability of the above code are very good.

However, everyone is worried that this writing method appeared after VS2017. This writing method is a compiler behavior. If you need to continue writing code in lower version VS, it is not recommended to use this code writing format.

3. Tips

Personally, I have read quite a lot of ancient codes, including one code I have seen a lot. Now there are three names that need to be separated and spliced. Most of the codes are as follows.

List<string> listName=new List<string>(){"Zhang San","Li Si","Wang Wu"};

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;

The individual is written as follows:

List<string> listName=new List<string>(){"Zhang San","Li Si","Wang Wu"};

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

The C# source code is as follows: 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();
    }
}

I write code and change code relatively quickly, because I consider readability, simplicity, whether it is common people's thinking and how convenient it is to change this place in every detail

Tags: C# Back-end

Posted on Thu, 04 Nov 2021 06:05:20 -0400 by Kingw