C# 10 新功能 -- 字串

C# 10 來了,首先要介紹的是關於字串的新改變。

字串常數使用字串插補功能

C# 10 的字串常數可以使用字串插捕功能來合併不同的字串常值,例如:

const string Score = "99";
const string Name = "Bill";
const string Description = $"{Name}'s Score is {Score}"; 

不過這有個地方需要注意就是必須所有的都是字串常值,如果改成以下的寫法在目前是無法編譯成功的,期待下一版能有機會更進一步。

 const int Score = 99;
 const string Name = "Bill";
 // 這會編譯失敗
 const string Description = $"{Name}'s Score is {Score}"; 
字串插補處理常式

C# 10 這次對於字串的改變中最有趣的就是這一個功能,過去編譯器對於字串插補的處理大致上就是轉換成 String.Format 或是 String.Concat,現在帶來了字串插補處理常式 (Interpolated string handler),我們可以自己定義一個型別來客製化字串插補的處理過程。

定義字串插補處理常式有幾項規定:

  1. 型別必須套用 InterpolatedStringHandlerAttribute 。
  2. 必須有一個具備兩個 int 型別參數 -- literalLength and formatCount 的建構式
  3. 公開方法 – public void AppendLiteral(string s)
  4. 公開方法 – public void AppendFormatted<T>(T t)

例如:

[InterpolatedStringHandler]
struct CustomStringHandler
{
    StringBuilder builder;
    public CustomStringHandler (int literalLength, int formatCount)
    {        
        builder = new StringBuilder(literalLength);
    }

    public void AppendLiteral(string s)
    {       
        builder.Append(s);
    }

    public void AppendFormatted<T>(T t)
    {
        builder.Append(t?.ToString());
    }

    public override string ToString()
    {
        return builder.ToString(); 
    }
}

稍微解釋一下裡面的意義:

  • 建構式中的第一個參數代表傳入的字串常值的字元數,例如 $"today is {day}",這個敘述中的常值字元數為 9 – today(5)、is(2)、空格(2);第二個參數代表插值的數量,意即格式化字串的數量,說白了就是有幾組 {} 啦,在 $"today is {day}" 就是一組。
  • AppendLiteral 方法會傳入字串常值。
  • AppendFormatted<T> 方法則是傳入插值的部分。
運作方式

我們建立以下的方法來解釋它是怎麼運作的:

 static void PrintText(CustomStringHandler handler)
 {
     Console.WriteLine(handler);
 }

接著我們這麼呼叫 PrintText 方法:

PrintText($"字串插值列印, 時間 {DateTime.Now}, 這是結尾");

編譯器會將程式碼拓展成以下型式:

 CustomStringHandler handler = new CustomStringHandler(17, 1);
 handler.AppendLiteral("字串插值列印, 時間 ");
 handler.AppendFormatted(DateTime.Now);
 handler.AppendLiteral(", 這是結尾");
 PrintText(handler.ToString());

這個功能有點裝飾器的感覺,可以在處理字串插捕的時候加入一些特定的處理。