2015/7/13

[C#] C# 6.0 中新字串格式化功能簡介

在 C# 6.0 中新增了方便的 String Interpolation 的功能, 它能進一步將原本的 string.Format 功能簡化。我們現在就可以使用 Visual Studio 2015 來做測試

原則上, 說穿了, 它只是透過一種全新的語法標示, 讓我們可以在原來的字串中, 把原先必須透過 string.Format() 方法才能辦到的字串格式化功能取代。當然, 如果你喜歡的話, 你還是可以繼續使用 string.Format()。不過, 說實在的, 以我個人的看法, C# 6.0 的這項新功能的確可以幫我們省下一些功夫, 提升工作效率。

開門見山。假設我們原本必須使用以下方法來格式一個字串:

lbResult.Text = 
string.Format("Name: {0} \nGendre: {1} \nBirthday: {2:D}", p.Name, p.Gendre, p.Birthday);

現在, 我們可以使用一個字串予以取代:

lbResult.Text = $"Name: {p.Name} \nGendre: {p.Gendre} \nBirthday: {p.Birthday:D}";

各位可以看出來, 我們只需在上述字串之前加上一個 $ 字號, 然後仿照原來要套用在 string.Format() 方法中的格式, 予以取代即可。如此, 我們就可以以更直覺的方式, 把 string.Format() 方法省略掉。

我寫了一個很小的 Demo 專案, 如下圖所示, 上方是設計畫面, 下方是執行畫面:

程式中依序有一個文字方塊: txtName, 還有兩個 RadioButton: radioMale 和 radioFemale, 以及三個 NumericUpDown: txtBdYear(設定 Value 為 2015), txtBdMonth(設定 Minimum 為 1,  Maximum 為 12, Value 為 1) 和 txtBdDay(設定 Minimum 為 1,  Maximum 為 31, Value 為 1)。右邊還有一用來顯示結果的 Label: lbResult。在上述控制項中加入 TextChanged 或 CheckedChange 或 ValueChanged 等事件處理函式, 通通指向 inputChanged() 方法 (參考以下程式)。

以下就是程式的部份:

namespace TestWinForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            initializeFields();
        }

        private void initializeFields()
        {
            txtBdYear.Maximum = DateTime.Now.Year;
            txtBdYear.Minimum = DateTime.Now.Year - 100;
            setValidBdDays();
        }

        private void setValidBdDays()
        {
            int daysInMonth = DateTime.DaysInMonth((int)txtBdYear.Value, (int)txtBdMonth.Value);
            txtBdDay.Maximum = daysInMonth;
        }

        private void inputChanged(object sender, EventArgs e)
        {
            if (sender is NumericUpDown)
                if (((NumericUpDown)sender).Name== "txtBdYear" || ((NumericUpDown)sender).Name == "txtBdMonth")
                    setValidBdDays();

            Profile p = new Profile();
            p.Name = txtName.Text ?? "(Unknown)";
            if (radioMale.Checked)
                p.Gendre = Gendre.Male;
            else if (radioFemale.Checked)
                p.Gendre = Gendre.Female;
            else p.Gendre = Gendre.Uncertain;
            p.Birthday = new DateTime((int)txtBdYear.Value, (int)txtBdMonth.Value, (int)txtBdDay.Value);

            //lbResult.Text = p.ToString();
            //lbResult.Text = $"Name: {p.Name} \nGendre: {p.Gendre} \nBirthday: {p.Birthday:D}";
            lbResult.Text = string.Format("Name: {0} \nGendre: {1} \nBirthday: {2:D}", p.Name, p.Gendre, p.Birthday);
        }
    }

    public class Profile
    {
        public string Name { get; set; }
        public Gendre Gendre { get; set; }
        public DateTime Birthday { get; set; }
        public override string ToString()
        {
            return $"Name: {this.Name} \nGendre: {this.Gendre} \nBirthday: {this.Birthday:D}";
        }
    }

    public enum Gendre:byte
    {
        Male,
        Female,
        Uncertain
    }
}

在程式中, 請找到 lbResult.Text = ... 這一段, 我示範了包括使用 string.Format() 等三種方法。這三種方法的結果都一樣, 讀者不妨自行體會。

在上述字串中以大刮號包住的語法中, 我們還可以插入有限度的外部功能, 例如:

lbResult.Text = 
$"Name: \"{p.Name.Trim()}\" \nGendre: {(byte)p.Gendre} \nBirthday: {p.Birthday:D}";

不過, 更複雜的語法就不被允許了。

 

沒有留言:

張貼留言