天天看點

C# 自定義格式化字元串說明符

大家好,今天我将為大家介紹 C# 中如何自定義格式化字元串說明符。

程式設計時候經常會用到 Console.WriteLine() 這個函數,其中必不可少的就是各種各樣的格式化說明符,他們負責将要輸出的字元串以各種形式輸出。但畢竟 C# 中定義好的格式化說明符有限,不能滿足所有人的需求,是以,自定義格式化說明符就顯得有必要了。

在學習之前,有必要先了解一下 Console.WriteLine() 函數的工作方式。

實際上,Console.WriteLine() 函數會将其所有的參數傳遞給靜态方法 String.Format() ,然後由該函數進行格式說明符的轉換。

String.Format() 形式如下:

string.Format(this.FormatProvider ,format ,neW object[](argO ,arg1....))
           

示例:

Console.WriteLine("hello world {0:E}", 123);
           

運作結果為:hello world 1.230000E+002

因為 "E" 表示以科學計數法表示 123 這個數而且結果的 "E" 大寫。而 Console.WriteLine() 将所有參數(此例中為兩個)傳遞給 String.Format() 方法, 該方法負責把格式化說明符轉換為相應的格式,進而構造出最終的結果。

但構造的過程不是建立一個 String 類的執行個體,而是一個 StringBuilder 類的執行個體(因為這個過程需要不斷改寫這個字元串執行個體,而 String 是不可變類型,每次改變都要創造一個新的字元串,會有額外的消耗,是以用 StringBuilder 類的執行個體,該類是專門應對需要更改字元串的情況的,詳情請參閱 MSDN)。

在構造的過程中,會先建立一個 StringBuilder 執行個體,并初始化為 "hello world"(實際上是初始化到第一個花括号前),然後不斷調用靜态方法 StringBuilder.Append() 和 StringBuilder.AppendFormat() 。前者負責花括号之前的字元串添加,後者負責對花括号的内容進行轉換。

而 StringBuilder.AppendFormat() 方法執行時會先檢查存儲值的對象是否實作 IFormattable 接口,如果實作了該接口,則會調用該接口提供的具有2個參數的方法 ToString() 。該接口定義如下:

interface IFormattable
{
    string ToString(string format,IFormatProvider formatProvider)
}
           

其中 format 就是格式化說明符,而 formatProvider 主要是用于提供背景文化資訊,如果為空,則是系統預設的背景文化資訊,此處不深究。

内置的類型都實作這個接口,可以對字元串進行格式化,如果是自己定義的類(結構體也可),則需要實作這個接口,才可以進行格式化,若不實作這個接口,則隻能調用對象本身的 ToString() 方法。

最後,ToString() 方法會傳回一個字元串,代替原來的花括号内容。

下面用一個坐标示例來示範:

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

namespace StringFormat
{
    class Program
    {
        static void Main(string[] args)
        {
            //開始測試,類定義在下面            
           
Vector v = new Vector(3, 2, 4);
            Console.WriteLine("以 xI+yJ+zK 的格式顯示");
            Console.WriteLine("{0:V}", v);
            Console.WriteLine("以 xi+yj+zk 的格式顯示");
            Console.WriteLine("{0:v}", v);
            Console.WriteLine("以數字形式顯示");
            Console.WriteLine("{0:N}", v);
            Console.WriteLine("以數字形式顯示");
            Console.WriteLine("{0:n}", v);
            Console.WriteLine("以大寫 E 科學計數法顯示");
            Console.WriteLine("{0:EE}", v);
            Console.WriteLine("以小寫 e 科學計數法顯示");
            Console.WriteLine("{0:ee}", v);
            Console.WriteLine("對象預設的 ToStrin() 方法顯示");
            Console.WriteLine("{0:a}", v);
            Console.ReadKey();
        }
    }

    //定義Vector類,實作IFomattable接口
    class Vector:IFormattable
    {
        double x, y, z; //定義三個坐标

        //構造函數
        public Vector(double x, double y, double z) 
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        //實作帶有兩個參數的ToString()方法
        public String ToString(String format, IFormatProvider formatProvide)
        {
            //根據format的值決定如何顯示
            switch (format)
            {
                //以 xI+yJ+zK 的格式顯示
                case "V":
                    StringBuilder sbV = new StringBuilder(x.ToString(), 30);
                    sbV.Append("I + ");
                    sbV.Append(y.ToString());
                    sbV.Append("J + ");
                    sbV.Append(z.ToString());
                    sbV.Append("K");
                    return sbV.ToString();

                //以 xi+yj+zk 的格式顯示
                case "v":
                    StringBuilder sbv = new StringBuilder(this.x.ToString(), 30);
                    sbv.Append("i + ");
                    sbv.Append(this.y.ToString());
                    sbv.Append("j + ");
                    sbv.Append(this.z.ToString());
                    sbv.Append("k");
                    return sbv.ToString();
                
                //以數字形式顯示
                case "N":
                case "n":
                   return String.Format("({0} ,{1}, {2})", x, y, z);
                
                //以大寫 E 科學計數法顯示
                case "EE":
                    return String.Format("{0:E} ,{1:E} ,{2:E}", x, y, z);

                //以小寫 e 科學計數法顯示
                case "ee":
                    return String.Format("{0:e} ,{1:e} ,{2:e}", x, y, z);
                
                //對象預設的 ToStrin() 方法顯示
                default:
                    return ToString();
            }
        }
    }
}
           

運作結果為:

C# 自定義格式化字元串說明符

本文就到此結束了,歡迎大家批評指正,一起交流!

Rember ,You Make Luck !