这些资料是我学习的时候在网络上寻找到的,发布出来希望对大家有帮助,一起努力前进,嘿嘿......Microsoft C#规范 2.0 版 GFC用户提交

feedsky 抓虾 pageflakes google reader my yahoo bloglines 鲜果 有道 http://wap.feedsky.com/bliplink

格式化概述

一、格式化概述



.NET Framework 提供了可自定义的、适于常规用途的格式化机制,可将值转换为适合显示的字符串。例如,可以将数值格式化为十六进制、科学记数法或者由用户指定的标点符号分隔成组的一系列数字。可以将日期和时间格式化为适合于特定的国家、地区或区域性。可以将枚举常数格式化为它的数值或名称。

您可以通过指定格式字符串和格式提供程序或使用默认设置来控制格式化。格式字符串包含一个或多个格式说明符字符,以指示如何转换值。格式提供程序提供了转换特定类型所需的其他控制、替换和区域性等方面的信息。

您可以通过实现 IFormattable 接口来重写 .NET Framework 解释格式化字符串的方法;通过实现 IFormatProvider 接口来提供您自己的格式提供程序;通过实现 ICustomFormatter 接口来执行您自己的格式化。

.NET Framework 提供了名为复合格式化的功能,它使用一个或多个格式字符串将一个或多个格式化值嵌入输出字符串。输出字符串可用于进行进一步处理,显示到系统控制台或者写入到流。

格式说明符

.NET Framework 定义了标准和自定义格式说明符,用于格式化数字、日期和时间以及枚举。各种格式化输出字符串的方法(例如 Console.WriteLine 和所有类型的 ToString方法),以及一些分析输入字符串的方法(例如 DateTime.ParseExact)都使用格式化说明符。

有关格式化数字数据的信息,请参见“数字格式字符串”。有关常用的数字格式说明符的列表,请参见“标准数字格式字符串”;有关自定义格式说明符(可用于创建自己的格式字符串)的列表,请参见“自定义数字格式字符串”。

关于格式化日期和时间的信息,请参见“日期与时间格式字符串”。有关常用日期和时间格式说明符的列表,请参见“标准 DateTime 格式字符串”;有关自定义时间和日期格式说明符(可用于创建自己的格式字符串)的列表,请参见“自定义 DateTime 格式字符串”。

有关格式化枚举的信息,以及标准枚举格式说明符的列表,请参见“枚举格式字符串”。

分析和格式说明符

格式化将类型的值转化为字符串表示形式;分析则与格式化相反,它是从字符串表示形式创建数据类型。格式提供程序控制如何执行分析,一些方法(例如 DateTime.ParseExact)采用格式说明符参数,可指示字符串表示形式的预期格式。有关分析的更多信息,请参见“分析字符串”。

ToString 和格式说明符

.NET Framework 支持重载类型的默认 ToString 方法,该方法执行基本格式化,ToString 的专用版本使用格式说明符参数来指示如何格式化值。有关更多信息,请参见“格式化基类型”和 IFormattable 接口。

格式提供程序

格式提供程序提供诸如此类的信息:格式化数字字符串时用作小数点的字符,或者格式化 DateTime 对象时使用的分隔字符。格式提供程序定义格式说明符用于格式化的字符,但不定义说明符本身。

格式提供程序可被传递到 IFormattable 接口所需的 ToString 重载;或者,如果没有传递格式提供程序,则使用格式化文本的方法预确定这种程序。

当没有传递格式提供程序时,信息或者被推断出,或者从 .NET Framework 中包含的某个标准格式提供程序中获取。通常,实现 IFormattable 的类也提供 ToString 的重载,该重载只接受格式说明符或格式提供程序。默认的 ToString 方法(不接受任何参数)是从 Object 类继承的。

有关数值数据的预定义格式提供程序的信息,请参见 NumberFormatInfo。有关日期和时间的预定义格式提供程序的信息,请参见 DateTimeFormatInfo。有关创建自定义格式提供程序或不同区域性的格式提供程序的信息,请参见 CultureInfo 和“不同区域性的格式设置”。

复合格式化

.NET Framework 的复合格式化功能受到诸如 String.Format 方法和 System.Console 以及 System.IO.TextWriter 的输出方法的支持,该功能



二、数字格式字符串


数字格式字符串用于控制在将数值数据类型表示为字符串时产生的格式化。存在于所有数值类型中的 ToString 重载(如格式化概述一节所述)可与某个数值数据类型共用,以控制数值类型转换为字符串时的精确行为。另外,数字格式字符串可以与几个类(如 Console StreamWriter)中的方法共用以格式化文本。数字格式字符串分为两类:标准格式字符串自定义格式字符串

请注意,无论什么格式字符串,如果浮点型(Single Double)是正无限或负无限,或者是 NaN(非数字),则格式化字符串分别是由当前的可用 NumberFormatInfo 对象指定的 PositiveInfinitySymbolNegativeInfinitySymbol NaNSymbol 的值。


标准数字格式字符串


标准数字格式字符串用于格式化通用数值类型。标准格式字符串采取“Axx”形式,其中“A”为单个字母字符(被称为格式说明符),“xx”是可选的整数(被称为精度说明符)。格式说明符必须是某个内置格式符。精度说明符的范围从 0 99,它控制有效位数或小数点右边零的个数。格式字符串不能包含空白。

如果格式字符串不包含某个标准格式说明符,则引发 FormatException。例如,格式字符串“z”会由于包含一个字母字符而被解释为标准数字格式字符串,但字母字符不属于标准数字格式说明符,所以会引发 FormatException。任何不符合标准数字格式字符串定义的数字格式字符串都被解释为自定义数字格式字符串。格式字符串“c!”包含两个字母字符,因此被解释为自定义格式字符串,尽管字符“c”是标准数字格式说明符。

下表描述了标准数字格式字符串。请注意,这些格式说明符产生的输出字符串受“区域选项”控制面板中的设置的影响。使用不同设置的计算机会生成不同的输出字符串。

格式说明符

名称

说明

C c

货币

数字转换为表示货币金额的字符串。转换由用于格式化数字的 NumberFormatInfo 对象的货币格式信息控制。精度说明符指示所需的小数位数。如果省略精度说明符,则使用 NumberFormatInfo 给定的默认货币精度。

D d

十进制数

只有整型才支持此格式。数字转换为十进制数字 (0-9) 的字符串,如果数字为负,则前面加负号。精度说明符指示结果字符串中所需的最少数字个数。如果需要的话,则用零填充该数字的左侧,以产生精度说明符给定的数字个数。

E e

科学计数法(指数)

数字转换为“-d.ddd…E+ddd”或“-d.ddd…e+ddd”形式的字符串,其中每个“d”表示一个数字 (0-9)。如果该数字为负,则该字符串以减号开头。小数点前总有一个数字。精度说明符指示小数点后所需的位数。如果省略精度说明符,则使用默认值,即小数点后六位数字。格式说明符的大小写指示在指数前加前缀“E”还是“e”。指数总是由正号或负号以及最少三位数字组成。如果需要,用零填充指数以满足最少三位数字的要求。

F f

固定点

数字转换为“-ddd.ddd…”形式的字符串,其中每个“d”表示一个数字 (0-9)。如果该数字为负,则该字符串以减号开头。精度说明符指示所需的小数位数。如果忽略精度说明符,则使用 NumberFormatInfo 给定的默认数值精度。

G g

常规

根据数字类型以及是否存在精度说明符,数字会转换为固定点或科学记数法的最紧凑形式。如果精度说明符被省略或为零,则数字的类型决定默认精度,如下表所示。

  • Byte SByte3

  • Int16 UInt165

  • Int32 UInt3210

  • Int64 UInt6419

  • Single7

  • Double15

  • Decimal29

如果用科学记数法表示数字时指数大于 -5 而且小于精度说明符,则使用固定点表示法;否则使用科学记数法。如果要求有小数点,并且忽略尾部零,则结果包含小数点。如果精度说明符存在,并且结果的有效数字位数超过指定精度,则通过舍入删除多余的尾部数字。使用科学记数法时,如果格式说明符是“G”,结果的指数带前缀“E”;如果格式说明符是“g”,结果的指数带前缀“e”

上述规则有一个例外:如果数字是 Decimal 而且省略精度说明符时。在这种情况下总使用固定点表示法并保留尾部零。

N n

数字

数字转换为“-d,ddd,ddd.ddd…”形式的字符串,其中每个“d”表示一个数字 (0-9)。如果该数字为负,则该字符串以减号开头。小数点左边每三个数字之间插入一个千位分隔符。精度说明符指示所需的小数位数。如果忽略精度说明符,则使用 NumberFormatInfo 给定的默认数值精度。

P p

百分比

数字转换为由 NumberFormatInfo.PercentNegativePattern 属性或 NumberFormatInfo.PercentPositivePattern 属性定义的、表示百分比的字符串。如果数字为负,则产生的字符串由 PercentNegativePattern 定义并以负号开头。已转换的数字乘以 100 以表示为百分比。精度说明符指示所需的小数位数。如果省略精度说明符,则使用 NumberFormatInfo 给定的默认数值精度。

R r

往返过程

往返过程说明符保证转换为字符串的数值再次被分析为相同的数值。使用此说明符格式化数值时,首先使用常规格式对其进行测试:Double 使用 15 位精度,Single 使用 7 位精度。如果此值被成功地分析回相同的数值,则使用常规格式说明符对其进行格式化。但是,如果此值未被成功地分析为相同数值,则它这样格式化:Double 使用 17 位精度,Single 使用 9 位精度。虽然精度说明符可以追加到往返过程格式说明符,但它将被忽略。使用此说明符时,往返过程优先于精度。此格式仅受浮点型支持。

X x

十六进制数

数字转换为十六进制数字的字符串。格式说明符的大小写指示对大于 9 的十六进制数字使用大写字符还是小写字符。例如,使用“X”产生“ABCDEF”,使用“x”产生“abcdef”。精度说明符指示结果字符串中所需的最少数字个数。如果需要的话,则用零填充该数字的左侧,以产生精度说明符给定的数字个数。只有整型才支持此格式。



自定义数字格式字符串


如果标准数字格式说明符未提供所需的格式化类型,可以使用自定义格式字符串进一步增强字符串输出。标准格式字符串包含一个字母字符,后面可能会跟有数字序列(形成一个 0 99 的值);而所有其他格式字符串都是自定义格式字符串。

下表显示可以用于创建自定义数字格式字符串及其定义的字符。请注意,与当前线程关联的 NumberFormatInfo 对象的“区域选项”控制面板的设置会影响这些字符中的某些所产生的输出字符串。使用不同区域性的计算机将生成不同的输出字符串。

格式字符

名称

说明

0

零占位符

如果格式化的值在格式字符串中出现“0”的位置有一个数字,则此数字被复制到输出字符串中。小数点前最左边的“0”的位置和小数点后最右边的“0”的位置确定总在输出字符串中出现的数字范围。“00”说明符使得值被舍入到小数点前最近的数字,其中零位总被舍去。例如,用“00”格式化 34.5 将得到值 35

#

数字占位符

如果格式化的值在格式字符串中出现“#”的位置有一个数字,则此数字被复制到输出字符串中。否则,输出字符串中的此位置不存储任何值。请注意,如果“0”不是有效数字,此说明符永不显示“0”字符,即使“0”是字符串中唯一的数字。如果“0”是所显示的数字中的有效数字,则显示“0”字符。“##”格式字符串使得值被舍入到小数点前最近的数字,其中零总被舍去。例如,用“##”格式化 34.5 将得到值 35

.

小数点

格式字符串中的第一个“.”字符确定格式化的值中的小数点分隔符的位置;任何其他“.”字符被忽略。用作小数点分隔符的实际字符由控制格式化的 NumberFormatInfo NumberDecimalSeparator 属性确定。

,

千位分隔符和数字比例换算

,”字符有两种用途。首先,如果格式字符串在小数点(如果有)左边的两个数字占位符(0 #)之间包含“,”字符,则输出将在小数点分隔符左边的每三个数字之间插入千位分隔符。输出字符串中用作小数点分隔符的实际字符由控制格式化的当前 NumberFormatInfo NumberGroupSeparator 属性确定。

其次,如果格式字符串在紧邻小数点的左侧包含一个或多个“,”字符,则数字在格式化之前将被“,”字符数除然后乘以 1000。例如,格式字符串“0,,”100,000,000 简单表示为 100。使用“,”字符指示比例换算在格式化数字中不包括千位分隔符。因此,若要将数字缩小 1,000,000 倍并插入千位分隔符,应使用格式字符串“#,##0,,”

%

百分比占位符

在格式字符串中出现“%”字符将导致数字在格式化之前乘以 100。适当的符号插入到数字本身在格式字符串中出现“%”的位置。使用的百分比字符由当前的 NumberFormatInfo 类确定。

E0

E+0

E-0

e0

e+0

e-0

科学计数法

如果“E”、“E+”、“E-”、“e”、“e+”或“e-”中的任何一个字符串出现在格式字符串中,而且后面紧跟至少一个“0”字符,则数字用科学计数法来格式化,在数字和指数之间插入“E”或“e”。跟在科学计数法指示符后面的“0”字符数确定指数输出的最小位数。“E+”和“e+”格式指示符号字符(正号或负号)应总是置于指数前面。“E”、“E-”、“e”或“e-”格式指示符号字符仅置于负指数前面。

\

转义符

C# C++ 中,反斜杠字符使格式字符串中的下一个字符被解释为转义序列。它与传统的格式化序列一起使用,如“\n”(换行)。

在某些语言中,转义符本身用作文本时必须跟在转义符之后。否则,编译器将该字符理解为转义符。使用字符串“\\”显示“\”

请注意,Visual Basic 中不支持此转义符,但是 ControlChars 提供相同的功能。

'ABC'

"ABC"

字符串

引在单引号或双引号中的字符被原样复制到输出字符串中,而且不影响格式化。

;

部分分隔符

;”字符用于分隔格式字符串中的正数、负数和零各部分。

其他

所有其他字符

所有其他字符以文本形式复制到输出字符串中它们出现的位置。

请注意,对于固定点格式字符串(不包含“E0”、“E+0”、“E-0”、“e0”、“e+0”或“e-0”的字符串),数字被舍入为与小数点右边的数字占位符数目相同的小数位数。如果格式字符串不包含小数点,数字被舍入为最接近的整数。如果数字位数多于小数点左边数字占位符的个数,多余的数字被复制到输出字符串中紧挨着第一个数字占位符的前面。

可以根据值为正、为负还是为零来为字符串应用不同的格式化。为产生这种行为,自定义格式字符串可以包含最多三个用分号分隔的部分:

  • 一个部分:格式字符串应用于所有值。

  • 两个部分:第一部分应用于正值和零,第二部分应用于负值。如果要格式化的数字为负,但根据第二部分中的格式舍入后为零,则最终的零根据第一部分进行格式化。

  • 三个部分:第一部分应用于正值,第二部分应用于负值,第三部分应用于零。第二部分可能为空(分号间没有任何内容),在这种情况下,第一部分应用于所有非零值。如果要格式化的数字为非零值,但根据第一部分或第二部分中的格式舍入后为零,则最终的零根据第三部分进行格式化。

格式化最终值时,此类型的格式化忽略所有先前存在的与数字关联的格式化。例如,使用部分分隔符时,显示的负值永远不带负号。如果您希望格式化后的最终值带有负号,则应明确包含负号,让它作为自定义格式说明符的组成部分。

三、日期与时间格式字符串


DateTime 格式字符串用于控制将日期或时间表示为字符串时所导致的格式化。

DateTime 数据类型实现 IFormattable,允许将其格式化为具有一个 DateTime.ToString 重载的字符串。标准格式字符串的输出受当前区域性影响。标准 .NET Framework 格式提供程序类是 DateTimeFormatInfo,它可以从传递的 CultureInfo 对象或者与当前线程关联的对象获得。

DateTime 格式字符串分为两类:标准格式字符串自定义格式字符串。自定义格式字符串允许在标准格式化字符串不起作用的情况下格式化 DateTime 对象。


标准 DateTime 格式字符串


标准 DateTime 格式字符串包含下表中的一个格式说明符字符。如果下表中没有该格式说明符,将引发运行时异常。如果格式字符串在长度上比单个字符长(即使多出的字符是空白),则格式字符串被解释为自定义格式字符串。

请注意,这些格式说明符产生的输出字符串受“区域选项”控制面板中的设置的影响。计算机的区域性设置或日期和时间设置不同,将生成不同的输出字符串。

格式字符串显示的时间和日期分隔符由与当前区域性的 DateTimeFormat 属性关联的 DateSeparator TimeSeparator 字符定义。然而,如果 InvariantCulture 被“r”、“s”和“u”说明符引用,与 DateSeparator TimeSeparator 字符关联的字符不随当前区域性更改。

下表描述了用来格式化 DateTime 对象的标准格式说明符。

格式说明符

名称

说明

d

短日期模式

显示由与当前线程关联的 DateTimeFormatInfo.ShortDatePattern 属性定义的模式或者由指定格式提供程序定义的模式。

D

长日期模式

显示由与当前线程关联的 DateTimeFormatInfo.LongDatePattern 属性定义的模式或者由指定格式提供程序定义的模式。

t

短时间模式

显示由与当前线程关联的 DateTimeFormatInfo.ShortTimePattern 属性定义的模式或者由指定格式提供程序定义的模式。

T

长时间模式

显示由与当前线程关联的 DateTimeFormatInfo.LongTimePattern 属性定义的模式或者由指定格式提供程序定义的模式。

f

完整日期/时间模式(短时间)

显示长日期和短时间模式的组合,由空格分隔。

F

完整日期/时间模式(长时间)

显示由与当前线程关联的 DateTimeFormatInfo.FullDateTimePattern 属性定义的模式或者由指定格式提供程序定义的模式。

g

常规日期/时间模式(短时间)

显示短日期和短时间模式的组合,由空格分隔。

G

常规日期/时间模式(长时间)

显示短日期和长时间模式的组合,由空格分隔。

M m

月日模式

显示由与当前线程关联的 DateTimeFormatInfo.MonthDayPattern 属性定义的模式或者由指定格式提供程序定义的模式。

R r

RFC1123 模式

显示由与当前线程关联的 DateTimeFormatInfo.RFC1123Pattern 属性定义的模式或者由指定格式提供程序定义的模式。这是定义的标准,并且属性是只读的;因此,无论所使用的区域性或所提供的格式提供程序是什么,它总是相同的。属性引用 CultureInfo.InvariantCulture 属性并遵照自定义模式“ddd, dd MMM yyyy HH:mm:ss G\MT”。请注意,“GMT”中的“M”需要转义符,因此它不被解释。格式化并不修改 DateTime 的值,所以您必须在格式化之前将值调整为 GMT

s

可排序的日期/时间模式;符合 ISO 8601

显示由与当前线程关联的 DateTimeFormatInfo.SortableDateTimePattern 属性定义的模式或者由指定格式提供程序定义的模式。属性引用 CultureInfo.InvariantCulture 属性,格式遵照自定义模式“yyyy-MM-ddTHH:mm:ss”

u

通用的可排序日期/时间模式

显示由与当前线程关联的 DateTimeFormatInfo.UniversalSortableDateTimePattern 属性定义的模式或者由指定格式提供程序定义的模式。因为它是定义的标准,并且属性是只读的,因此无论区域性或格式提供程序是什么,模式总是相同的。格式化遵照自定义模式“yyyy-MM-dd HH:mm:ssZ”。格式化日期和时间时不进行时区转换;所以,请在使用格式说明符之前将本地日期和时间转换为通用时间。

U

通用的可排序日期/时间模式

显示由与当前线程关联的 DateTimeFormatInfo.FullDateTimePattern 属性定义的模式或者由指定格式提供程序定义的模式。显示的时间为通用时间而不是本地时间,等效于 DateTime 值。

Y y

年月模式

显示由与当前线程关联的 DateTimeFormatInfo.YearMonthPattern 属性定义的模式或者由指定格式提供程序定义的模式。

任何其他单个字符

未知说明符

   


自定义 DateTime 格式字符串


通过使用自定义 DateTime 格式说明符来创建自己的自定义 DateTime 格式字符串,您可以更好地控制格式化 DateTime 对象的方式。组合一个或多个自定义格式说明符,以构造可生成您喜欢的输出的 DateTime 格式化模式。实际上,大多数的标准 DateTime 格式说明符都是在当前适用的 DateTimeFormatInfo 类中指定的格式化模式的别名。

下表描述了自定义格式说明符以及它们产生的结果。这些格式说明符的输出受“区域选项”控制面板中的当前区域性和设置的影响。

格式说明符

说明

d

显示月份的当前日期,以 1 31 之间的一个数字表示,包括 1 31。如果日期只有一位数字 (1-9),则它显示为一位数字。

请注意,如果“d”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准短日期模式格式说明符。如果“d”格式说明符与其他自定义格式说明符或者“%”字符一起传递,则它被解释为自定义格式说明符。

dd

显示月份的当前日期,以 1 31 之间的一个数字表示,包括 1 31。如果日期只有一位数字 (1-9),则将其格式化为带有前导 0 (01-09)

ddd

显示指定的 DateTime 的日期部分缩写名称。如果未提供特定的有效格式提供程序(实现具有预期属性的 IFormatProvider 的非空对象),则使用 DateTimeFormat AbbreviatedDayNames 属性及其与当前所使用线程关联的当前区域性。否则,使用来自指定格式提供程序的 AbbreviatedDayNames 属性。

dddd(外加任意数量的附加“d”字符)

显示指定的 DateTime 的日期全名。如果未提供特定的有效格式提供程序(一个非空对象,可实现具有预期属性的 IFormatProvider),则使用 DateTimeFormat DayNames 属性及其与当前所使用线程关联的当前区域性。否则,使用来自指定格式提供程序的 DayNames 属性。

f

显示秒部分的最高有效位。

请注意,如果“f”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为完整的(长日期 + 短时间)格式说明符。如果“f”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

使用 System.DateTime.ParseExact 方法进行分析时,所使用的“f”格式说明符的位数指示要分析的秒部分的最高有效位的位数。

ff

显示秒部分的两个最高有效位。

fff

显示秒部分的三个最高有效位。

ffff

显示秒部分的四个最高有效位。

fffff

显示秒部分的五个最高有效位。

ffffff

显示秒部分的六个最高有效位。

fffffff

显示秒部分的七个最高有效位。

F

显示秒部分的最高有效位。如果该位为零,则不显示任何信息。

使用 System.DateTime.ParseExact(System.String,System.String,System.IFormatProvider) 方法进行分析时,所使用的“F”格式说明符的位数指示要分析的秒部分的最高有效位最大数。

FF

显示秒部分的两个最高有效位。但不显示尾随零(或两个零位)。

FFF

显示秒部分的三个最高有效位。但不显示尾随零(或三个零位)。

FFFF

显示秒部分的四个最高有效位。但不显示尾随零(或四个零位)。

FFFFF

显示秒部分的五个最高有效位。但不显示尾随零(或五个零位)。

FFFFFF

显示秒部分的六个最高有效位。但不显示尾随零(或六个零位)。

FFFFFFF

显示秒部分的七个最高有效位。但不显示尾随零(或七个零位)。

g gg(外加任意数量的附加“g”字符)

显示指定的 DateTime 的年代部分(例如 A.D.)。如果未提供特定的有效格式提供程序(一个非空对象,可实现具有预期属性的 IFormatProvider),则年代由与 DateTimeFormat 关联的日历及其与当前线程关联的当前区域性确定。

请注意,如果“g”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准常规格式说明符。如果“g”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

h

1 12 范围中的一个数字显示指定的 DateTime 的小时数,该小时数表示自午夜(显示为 12)或中午(也显示为 12)后经过的整小时数。如果单独使用这种格式,则无法区别某一小时是中午以前还是中午以后的时间。如果该小时是单个数字 (1-9),则它显示为单个数字。显示小时时不发生任何舍入。例如,DateTime 5:43 时返回 5

hh, hh(外加任意数量的附加“h”字符)

1 12 范围中的一个数字显示指定的 DateTime 的小时数,该小时数表示自午夜(显示为 12)或中午(也显示为 12)后经过的整小时数。如果单独使用这种格式,则无法区别某一小时是中午以前还是中午以后的时间。如果该小时是单个数字 (1-9),则将其格式化为前面带有 0 (01-09)

H

0 23 范围中的一个数字显示指定的 DateTime 的小时数,该小时数表示自午夜(显示为 0)后经过的整小时数。如果该小时是单个数字 (0-9),则它显示为单个数字。

HH, HH(外加任意数量的附加“H”字符)

0 23 范围中的一个数字显示指定的 DateTime 的小时数,该小时数表示自午夜(显示为 0)后经过的整小时数。如果该小时是单个数字 (0-9),则将其格式化为前面带有 0 (01-09)

m

0 59 范围中的一个数字显示指定的 DateTime 的分钟数,该分钟数表示自上一小时后经过的整分钟数。如果分钟是一位数字 (0-9),则它显示为一位数字。

请注意,如果“m”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准的月日模式格式说明符。如果“m”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

mm, mm(外加任意数量的附加“m”字符)

0 59 范围中的一个数字显示指定的 DateTime 的分钟数,该分钟数表示自上一小时后经过的整分钟数。如果分钟是一位数字 (0-9),则将其格式化为带有前导 0 (01-09)

M

显示月份,以 1 12 之间(包括 1 12)的一个数字表示。如果月份是一位数字 (1-9),则它显示为一位数字。

请注意,如果“M”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准的月日模式格式说明符。如果“M”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

MM

显示月份,以 1 12 之间(包括 1 12)的一个数字表示。如果月份是一位数字 (1-9),则将其格式化为带有前导 0 (01-09)

MMM

显示指定的 DateTime 的月部分缩写名称。如果未提供特定的有效格式提供程序(一个非空对象,可实现具有预期属性的 IFormatProvider),则使用 DateTimeFormat AbbreviatedMonthNames 属性及其与当前线程关联的当前区域性。否则,使用来自指定格式提供程序的 AbbreviatedMonthNames 属性。

MMMM

显示指定的 DateTime 的月的全名。如果未提供特定的有效格式提供程序(一个非空对象,可实现具有预期属性的 IFormatProvider),则使用 DateTimeFormat MonthNames 属性及其与当前线程关联的当前区域性。否则,使用来自指定格式提供程序的 MonthNames 属性。

s

0 59 范围中的一个数字显示指定的 DateTime 的秒数,该秒数表示自上一分钟后经过的整秒数。如果秒是一位数字 (0-9),则它仅显示为一位数字。

请注意,如果“s”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准的可排序日期/时间模式格式说明符。如果“s”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

ss, ss(外加任意数量的附加“s”字符)

0 59 范围中的一个数字显示指定的 DateTime 的秒数,该秒数表示自上一分钟后经过的整秒数。如果秒是一位数字 (0-9),则将其格式化为带有前导 0 (01-09)

t

显示指定的 DateTime A.M./P.M. 指示项的第一个字符。如果未提供特定的有效格式提供程序(一个非空对象,可实现具有预期属性的 IFormatProvider),则使用 DateTimeFormat AMDesignator(或 PMDesignator)属性及其与当前线程关联的当前区域性。否则,使用来自指定 IFormatProvider AMDesignator(或 PMDesignator)属性。如果对于指定的 DateTime 所经过的总整小时数小于 12,则使用 AMDesignator。否则,使用 PMDesignator

请注意,如果“t”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准的长时间模式格式说明符。如果“t”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

tt, tt(外加任意数量的附加“t”字符)

显示指定的 DateTime A.M./P.M. 指示项。如果未提供特定的有效格式提供程序(一个非空对象,可实现具有预期属性的 IFormatProvider),则使用 DateTimeFormat AMDesignator(或 PMDesignator)属性及其与当前线程关联的当前区域性。否则,使用来自指定 IFormatProvider AMDesignator(或 PMDesignator)属性。如果对于指定的 DateTime 所经过的总整小时数小于 12,则使用 AMDesignator。否则,使用 PMDesignator

y

最多用两位数字显示指定的 DateTime 的年份。忽略年的前两位数字。如果年份是一位数字 (1-9),则它显示为一位数字。

请注意,如果“y”格式说明符单独使用,没有其他自定义格式字符串,则它被解释为标准短日期模式格式说明符。如果“y”格式说明符与其他自定义格式说明符或“%”字符一起传递,则它被解释为自定义格式说明符。

yy

最多用两位数字显示指定的 DateTime 的年份。忽略年的前两位数字。如果年份是一位数字 (1-9),则将其格式化为带有前导 0 (01-09)

yyyy

显示指定的 DateTime 的年份部分(包括纪元)。如果年份长度小于四位,则按需要在前面追加零以使显示的年份长度达到四位。

z

仅以整小时数为单位显示系统当前时区的时区偏移量。偏移量总显示为带有前导符号(零显示为“+0”),指示早于格林威治时间 (+) 或迟于格林威治时间 (-) 的小时数。值的范围是 -12 +13。如果偏移量为一位数 (0-9),则将其显示为带有合适前导符号的一位数。时区设置以 +X 或 –X 的形式指定,其中 X 是相对于 GMT 的小时偏差。显示的偏差受夏时制的影响。

zz

仅以整小时数为单位显示系统当前时区的时区偏移量。偏移量总显示为带有前导或尾随符号(零显示为“+00”),指示早于格林威治时间 (+) 或迟于格林威治时间 (-) 的小时数。值范围为 -12 +13。如果偏移量为一位数 (0-9),则将其格式化为前面带有 0 (01-09) 并带有适当的前导符号。时区设置以 +X 或 –X 的形式指定,其中 X 是相对于 GMT 的小时偏差。显示的偏差受夏时制的影响。

zzz, zzz(外加任意数量的附加“z”字符)

以小时和分钟为单位显示系统当前时区的时区偏移量。偏移量总是显示为带有前导或尾随符号(零显示为“+00:00”),指示早于格林威治时间 (+) 或迟于格林威治时间 (-) 的小时数。值范围为 -12:00 +13:00。如果偏移量为一位数 (0-9),则将其格式化为前面带有 0 (01-09) 并带有适当的前导符号。时区设置以 +X 或 –X 的形式指定,其中 X 是相对于 GMT 的小时偏差。显示的偏差受夏时制的影响。

:

时间分隔符。

/

日期分隔符。

"

带引号的字符串。显示转义符 (/) 之后两个引号之间的任何字符串的文本值。

'

带引号的字符串。显示两个“'”字符之间的任何字符串的文本值。

%c

其中 c 既是标准格式说明符又是自定义格式说明符,显示与格式说明符关联的自定义格式模式。

请注意,如果格式说明符作为单个字符来单独使用,它将被解释成标准格式说明符。只有包含两个或更多字符的格式说明符被解释为自定义格式说明符。说明符可以被同时定义为标准和自定义格式说明符,要显示此种说明符的自定义格式,请在说明符之前加“%”符号。

\c

其中 c 是任意字符,转义符将下一个字符显示为文本。在此上下文中,转义符不能用于创建转义序列(如“\n”表示换行)。

任何其他字符

其他字符作为文本直接写入输出字符串。

DateTime.ToString 传递自定义模式时,模式必须至少为两个字符长。如果只传递“d”,则公共语言运行库将其解释为标准格式说明符,这是因为所有单个格式说明符都被解释为标准格式说明符。如果传递单个“h”,则引发异常,原因是不存在标准的“h”格式说明符。若要只使用单个自定义格式进行格式化,请在说明符的前面或后面添加一个空格。例如,格式字符串“h”被解释为自定义格式字符串。



四、枚举格式字符串


可以使用 ToString 方法创建新的字符串对象,以表示 Enum 的数字、十六进制或字符串值。此方法采用某个枚举格式化字符串指定希望返回的值。

下表列出了枚举格式化字符串及其返回的值。这些格式说明符不区分大小写。

格式字符串

结果

G g

如有可能,将枚举项显示为字符串值,否则显示当前实例的整数值。如果枚举定义中设置了 Flags 属性,则串联每个有效项的字符串值并将各值用逗号分开。如果未设置 Flags 属性,则将无效值显示为数字项。

F f

如有可能,将枚举项显示为字符串值。如果值可以完全显示为枚举项的总和(即使未提供 Flags 属性),则串联每个有效项的字符串值并将各值用逗号分开。如果值不能完全由枚举项确定,则将值格式化为整数值。

D d

以尽可能短的表示形式将枚举项显示为整数值。

X x

将枚举项显示为十六进制值。按需要将值表示为带有前导零,以确保值的长度最少有八位。

下面的示例定义一个名为 Colors 的枚举,该枚举包含三项:RedBlue Green

C# 

复制代码

public enum Colors{Red = 1, Blue = 2, Green = 3}

定义了枚举后,可以按下面的方式声明实例。

C# 

复制代码

Colors MyColors = Colors.Green;

下面的示例使用枚举格式化方法将 DayOfWeek 枚举的字符串、数字和十六进制表示形式赋予字符串 MyString。此代码创建 DayOfWeek 枚举的新实例(名为 MyDays),并为其赋值 Friday。然后,它使用“G”、“F”、“D”和“X”格式化字符串将不同的枚举表示形式赋予 MyString

C# 

复制代码

DayOfWeek MyDays = DayOfWeek.Friday;


String MyString = MyDays.ToString("G");

// In the U.S. English culture, MyString has the value: "Friday".


MyString = MyDays.ToString("F");

// In the U.S. English culture, MyString has the value: "Friday".


MyString = MyDays.ToString("D");

// In the U.S. English culture, MyString has the value: "5".


MyString = MyDays.ToString("X");

// In the U.S. English culture, MyString has the value: "00000005".

五、复合格式化


通过 .NET Framework 复合格式化功能,您可以提供值列表和由交替出现的固定文本和索引占位符组成的源字符串,还能轻松地获得由夹杂着格式化值的原始固定文本组成的结果字符串。复合格式化可以用于一些方法,如 String.Format(返回格式化字符串)方法和 Console.WriteLine(将输出字符串显示到控制台)方法等,也可用于 TextWriter.WriteLine(将输出字符串写到流或文件)的实现。

每个索引占位符或格式项都对应值列表中的一个元素。复合格式化功能返回新的输出字符串,其中嵌入源字符串的每个格式项都被对应的格式化值替换。

源字符串包含被一个或多个格式项分隔开的零个或多个固定文本段。固定文本可以包含您选择的任何内容。

下面是一个 String.Format 示例。

C# 

复制代码

string myName = "Fred";

String.Format("Name = {0}, hours = {1:hh}", myName, DateTime.Now);

固定文本为“Name = 和“, hours = 。格式项为“{0}和“{1:hh}。值列表为 myName DateTime.Now

格式项语法

所有格式项都采用下面的形式。

{index[,alignment][:formatString]}

必须使用成对的大括号(“{”和“}”)。

格式项组件

格式项由下面的组件构成。

索引组件

强制“索引”组件(也叫参数说明符)是一个从 0 开始的数字,可标识值列表中对应的元素。也就是说,参数说明符为 0 的格式项格式化列表中的第一个值,参数说明符为 1 的格式项格式化列表中的第二个值,依次类推。

通过指定相同的参数说明符,多个格式项可以引用值列表中的同一个元素。例如,通过指定类似于“{0:X} {0:E} {0:N}”的源字符串,可以将同一个数值格式化为十六进制、科学表示法和数字格式。

每一个格式项都可以引用所有的参数。例如,如果有三个值,则可以通过指定类似于“{1} {0} {2}”的源字符串来格式化第二、第一和第三个值。格式项未引用的值会被忽略。如果参数说明符指定了超出值列表范围的项,将导致运行时异常。

对齐组件

可选的“对齐”组件是一个带符号的整数,指示首选的格式化字段宽度。如果“对齐”值小于格式化字符串的长度,“对齐”会被忽略,并且使用格式化字符串的长度作为字段宽度。如果“对齐”为正数,字段的格式化数据为右对齐;如果“对齐”为负数,字段的格式化数据为左对齐。如果需要填充,则使用空白。如果指定“对齐”,就需要使用逗号。

格式字符串组件

可选的“格式字符串”组件由标准或自定义格式说明符组成。如果不指定“格式字符串”,则使用常规(“G”)格式说明符。如果指定“格式说明符”,需要使用冒号。

转义大括号

左大括号和右大括号被解释为格式项的开始和结束。因此,必须使用转义序列显示文本左大括号或右大括号。在固定文本中指定两个左大括号 ("{{") 以显示一个左大括号 ("{"),或指定两个右大括号 ("}}") 以显示一个右大括号 ("}")。按照在格式项中遇到大括号的顺序依次解释它们。不支持解释嵌套的大括号。

解释转义大括号的方式会导致意外的结果。例如,考虑要显示一个左大括号、一个格式化为十进制数的数值和一个右大括号的格式项“{{{0:D}}}”。但是,实际是按照以下方式解释该格式项:

  1. 前两个左大括号 ("{{") 被转义,生成一个左大括号。

  2. 之后的三个字符 ("{0:") 被解释为格式项的开始。

  3. 下一个字符 ("D") 将被解释为 Decimal 标准数值格式说明符,但后面的两个转义大括号 ("}}") 生成单个大括号。由于得到的字符串 ("D}") 不是标准数值格式说明符号,所以得到的字符串会被解释为用于显示字符串“D}”的自定义格式字符串。

  4. 最后一个大括号 ("}") 被解释为格式项的结束。

  5. 显示的最终结果是字符串“{D}”。不会显示本来要格式化的数值。

在编写代码时,避免错误解释转义大括号和格式项的一种方法是单独显示大括号和格式项。也就是说,显示左大括号,再显示格式项的结果,然后显示右大括号。

处理顺序

如果要格式化的值是 null(在 Visual Basic 中为 Nothing),则返回空字符串 ("")

如果要格式化的类型实现 ICustomFormatter 接口,则调用 ICustomFormatter.Format 方法。

如果前面的步骤未格式化类型,并且该类型实现 IFormattable 接口,则调用 IFormattable.ToString 方法。

如果前面的步骤未格式化类型,则调用该类型的 ToString 方法(从 Object 类继承而来)。

前面的步骤执行完毕之后应用对齐。

代码示例

下面的示例显示使用复合格式化创建的一个字符串和使用对象的 ToString 方法创建的另一个字符串。两种格式化类型产生相同的结果。

C# 

复制代码

string FormatString1 = String.Format("{0:dddd MMMM}", DateTime.Now);

string FormatString2 = DateTime.Now.ToString("dddd MMMM");

假定当前日期是五月的星期四,在美国英语区域性中上述示例中的两个字符串的值都是 Thursday May

Console.WriteLine String.Format 公开相同功能。两种方法的唯一差异是 String.Format 将其结果作为字符串返回,而 Console.WriteLine 将结果写入与 Console 对象关联的输出流。下面的示例使用 Console.WriteLine 方法将 MyInt 的值格式化为货币值。

C# 

复制代码

int MyInt = 100;

Console.WriteLine("{0:C}", MyInt);

此代码在当前区域性为美国英语的计算机上,将 $100.00 显示到控制台。

下面的示例说明格式化多个对象,包括用两种不同的方式格式化一个对象。

C# 

复制代码

string myName = "Fred";

String.Format("Name = {0}, hours = {1:hh}, minutes = {1:mm}",

myName, DateTime.Now);

以上字符串的输出是“Name = Fred, hours = 07, minutes = 23,其中当前的时间反映了这些数字。

下列示例说明了对齐在格式化中的使用。格式化的参数放置在竖线字符 (|) 之间以突出显示得到的对齐。

C# 

复制代码

string myFName = "Fred";

string myLName = "Opals";

int myInt = 100;

string FormatFName = String.Format("First Name = |{0,10}|", myFName);

string FormatLName = String.Format("Last Name = |{0,10}|", myLName);

string FormatPrice = String.Format("Price = |{0,10:C}|", myInt);

Console.WriteLine(FormatFName);

Console.WriteLine(FormatLName);

Console.WriteLine(FormatPrice);


FormatFName = String.Format("First Name = |{0,-10}|", myFName);

FormatLName = String.Format("Last Name = |{0,-10}|", myLName);

FormatPrice = String.Format("Price = |{0,-10:C}|", myInt);

Console.WriteLine(FormatFName);

Console.WriteLine(FormatLName);

Console.WriteLine(FormatPrice);

在美国英语区域性中,上述代码将下列内容显示到控制台。不同的区域性显示不同的货币符号和分隔符。

 

复制代码

First Name = | Fred|

Last Name = | Opals|

Price = | $100.00|

First Name = |Fred |

Last Name = |Opals |

Price = |$100.00 |



六、自定义格式字符串


.NET Framework 支持扩展其内置格式化机制,这样,您可以创建自己的接受用户定义格式字符串的 ToString 方法,或者,创建格式提供程序来调用您自己的 Format 方法以执行类型的自定义格式化。您可以通过实现 IFormattable 接口来创建自己的 ToString 方法,还可以通过实现 ICustomFormatter IFormatProvider 接口来创建自己的 Format 方法。

本节的信息局限于向用户定义类型和现有基类型添加自定义格式字符串,但所描述的原则可以应用到任何类型。

添加自定义类型的自定义格式字符串

如果要创建自己的自定义类型,您可以通过实现 IFormattable 接口以及该接口的 ToString 方法来添加对处理您自己的自定义格式字符串的支持。这意味着您可以控制哪些格式字符串会被您的自定义类型识别。实现 IFormattable 接口(而不只是将 ToString 方法添至您的自定义类型)的好处在于:您可以保证 ToString 方法的用户能够使用预定义的调用语法和返回类型。

IFormattable 接口的 ToString 方法带有一个格式字符串参数和一个格式提供程序参数。如果格式字符串参数为空字符串或 null(在 Visual Basic 中为 Nothing),则执行默认格式化。如果格式提供程序为 null,则使用默认格式提供程序。

如果自定义格式字符串被传递到您的自定义版本的 ToString,则执行适当的格式化;否则调用合适的 .NET Framework 方法来执行标准格式化。

在下面的示例中,MyType 自定义类型实现 IFormattable 接口。如果您创建一个新的 MyType 类实例,并将自定义格式字符串“b”传递给该实例的 ToString 方法,则 Convert.ToString 的重载返回该实例的值的二进制(基 2)字符串表示形式。如果没有传递“b”,该实例将用自己的 ToString 方法格式化它的值;也就是说,用 System.Int32.ToString 方法格式化整数 myValue

C# 

复制代码

public class MyType : IFormattable

{

// Assign a value for the class.

private int myValue;

// Add a constructor.

public MyType( int value )

{

myValue = value;

}

// Write a custom Format method for the type.

public string ToString(string format, IFormatProvider fp)

{

if (format.Equals ("b"))

{

return Convert.ToString (myValue, 2);

}

else

{

return myValue.ToString(format, fp);

}

}

}

下面的示例说明如何使用 MyType 类和格式字符串“b”

C# 

复制代码

MyType mtype = new MyType(42);

String MyString = mtype.ToString("b", null);

String YourString = mtype.ToString("p", null);

// MyString has the value: "101010".

// YourString has the value: "42 %".

向现有类型添加自定义格式字符串

通过创建实现 ICustomFormatter IFormatProvider 的格式提供程序类,您可以控制如何格式化现有的基类型,以及提供用于格式化的附加代码。

当向基类型的 ToString 方法传递格式提供程序时,基类型使用传递的格式提供程序(而不是默认的格式提供程序)定义它的格式化规则。若要创建自定义格式提供程序,应执行下列操作:

  1. 定义一个类,该类实现上述两个接口并重写 GetFormat Format

  2. 将该类传入将 IFormatProvider 作为参数的方法(如 String.Format)。这样做使 String.Format 可以识别在新格式提供程序类中定义的自定义格式方案。

下面的示例定义了一个添加自定义 Format 方法的类,此方法可以产生一个整数的不同基值。

C# 

复制代码

public class MyFormat : IFormatProvider, ICustomFormatter

{

// String.Format calls this method to get an instance of an

// ICustomFormatter to handle the formatting.

public object GetFormat (Type service)

{

if (service == typeof (ICustomFormatter))

{

return this;

}

else

{

return null;

}

}

// After String.Format gets the ICustomFormatter, it calls this format

// method on each argument.

public string Format (string format, object arg, IFormatProvider provider)

{

if (format == null)

{

return String.Format ("{0}", arg);

}

// If the format is not a defined custom code,

// use the formatting support in ToString.

if (!format.StartsWith("B"))

{

//If the object to be formatted supports the IFormattable

//interface, pass the format specifier to the

//objects ToString method for formatting.

if (arg is IFormattable)

{

return ((IFormattable)arg).ToString(format, provider);

}

//If the object does not support IFormattable,

//call the objects ToString method with no additional

//formatting.

else if (arg != null)

{

return arg.ToString();

}

}

// Uses the format string to

// form the output string.

format = format.Trim (new char [] {'B'});

int b = Convert.ToInt32 (format);

return Convert.ToString ((int)arg, b);

}

}

在下面的示例中,String.Format 方法使用 MyFormat 中定义的自定义 Format 方法来显示 MyInt 的基 16 表示形式。

C# 

复制代码

int MyInt = 42;

string MyString = String.Format (new MyFormat (), "{0} in the custom B16 format is {1:B16}", new object [] { MyInt, MyInt } );

// MyString has the value: "42 in custom B16 format is 2a".


七、IFormattable 接口


提供将对象的值格式化为字符串表示形式的功能。

命名空间:System
程序集:mscorlib(在 mscorlib.dll 中)

语法


C#

[ComVisibleAttribute(true)]

public interface IFormattable


IFormattable 成员

公共方法


名称

说明

ToString

使用指定的格式格式化当前实例的值。



备注

IFormattable 由基础数据类型实现。

格式描述对象在转换为字符串时的外观。格式可以是标准的,也可以是自定义的。标准格式采用 Axx 的形式,其中 A 是称为格式说明符的字母型字符,xx 是称为精度说明符的非负整数。格式说明符控制应用于表示为字符串的值的格式化类型。精度说明符控制字符串中的有效位数或小数位数(如果适用)。

当格式包括随区域性变化的符号(如由“C”和“c”格式表示的货币符号)时,格式化对象提供字符串表示形式中使用的实际字符。方法可以包括一个参数来传递提供格式化对象的 IFormatProvider 对象,或者可以使用默认的格式化对象,该对象包含当前线程的符号定义。当前线程通常使用默认情况下系统范围内使用的同一符号集。

给实现者的说明需要的字符串格式化控制比 Object.ToString 提供的多的类应实现 IFormattable,后者的 ToString 方法使用当前线程的 CurrentCulture 属性。实现 IFormattable 的类必须支持“G”(常规)格式化代码。除“G”代码外,该类还可以定义它支持的格式化代码的列表。有关格式化和格式化代码的更多信息,请参见格式化概述。

示例

下面的示例演示如何定义实现 IFormattable 接口的类型。此示例还演示如何调用 IFormattable 接口的 ToString 方法。

C# 

复制代码

using System;


class Point : IFormattable

{

public int x, y;


public Point(int x, int y)

{

this.x = x;

this.y = y;

}


public override String ToString() { return ToString(null, null); }


public String ToString(String format, IFormatProvider fp)

{

// If no format is passed, display like this: (x, y).

if (format == null) return String.Format("({0}, {1})", x, y);


// For "x" formatting, return just the x value as a string

if (format == "x") return x.ToString();


// For "y" formatting, return just the y value as a string

if (format == "y") return y.ToString();


// For any unrecognized format, throw an exception.

throw new FormatException(String.Format("Invalid format string: '{0}'.", format));

}

}



public sealed class App

{

static void Main()

{

// Create the object.

Point p = new Point(5, 98);


// Test ToString with no formatting.

Console.WriteLine("This is my point: " + p.ToString());


// Use custom formatting style "x"

Console.WriteLine("The point's x value is {0:x}", p);


// Use custom formatting style "y"

Console.WriteLine("The point's y value is {0:y}", p);


try

{

// Use an invalid format; FormatException should be thrown here.

Console.WriteLine("Invalid way to format a point: {0:XYZ}", p);

}

catch (FormatException e)

{

Console.WriteLine("The last line could not be displayed: {0}", e.Message);

}

}

}


// This code produces the following output.

//

// This is my point: (5, 98)

// The point's x value is 5

// The point's y value is 98

// The last line could not be displayed: Invalid format string: 'XYZ'.



IFormatProvider 接口

提供用于检索控制格式化的对象的机制。

命名空间:System
程序集:mscorlib(在 mscorlib.dll 中)

语法


C#

[ComVisibleAttribute(true)]

public interface IFormatProvider


备注

公共语言运行库中的一些方法可以在数值和字符串表示形式之间进行相互转换,这些方法采用字符串参数,该参数包含一个或多个称为格式说明符的字符,这些字符指示如何转换数值。如果格式说明符的含义因区域性而异,则格式化对象提供字符串表示形式中所用的实际字符。

类或数值类型实现此接口的 GetFormat 方法,以获得提供格式信息或实现类型的处理的对象。

例如,IFormatProvider NumberFormatInfo DateTimeFormatInfo 实现。NumberFormatInfo 提供用于格式化基本数据类型的数字的区域性特定信息,而 DateTimeFormatInfo 提供用于格式化日期和时间值的区域性特定信息。

示例

下面的代码示例阐释了如何使用一个类来实现 IFormatProvider 接口和 GetFormat 方法。AnyRadix 类支持“Ra”格式设置代码,并将 Int64 值转换为介于 2 36 之间的任何指定基数的字符串。如果 Type 参数引用的类实现 ICustomFormatter,则 GetFormat 返回对其自身的引用;否则,GetFormat 返回空引用(在 Visual Basic 中为 Nothing)。


C# 

复制代码

// Sample for the IFormatProvider interface and

// the IFormatProvider.GetFormat( Type ) method.

using System;


// This class implements the "Ra" formatting code. An instance of this

// class should be passed to methods requiring an IFormatProvider.

public class AnyRadix : ICustomFormatter, IFormatProvider

{

// The value to be formatted is returned as a signed string

// of digits from the rDigits array.

const string radixCode = "Ra";

private static char[] rDigits = {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',

'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',

'U', 'V', 'W', 'X', 'Y', 'Z' };

// This method returns an object that implements ICustomFormatter

// to do the formatting.

public object GetFormat( Type argType )

{

// Here, the same object (this) is returned, but it would

// be possible to return an object of a different type.

if ( argType == typeof( ICustomFormatter ) )

return this;

else

return null;

}

// This method does the formatting only if it recognizes the

// format codes.

public string Format( string formatString,

object argToBeFormatted, IFormatProvider provider )

{

// If no format string is provided or the format string cannot

// be handled, use IFormattable or standard string processing.

if( formatString == null ||

! formatString.Trim( ).StartsWith( radixCode ) )

{

if( argToBeFormatted is IFormattable )

return ( (IFormattable)argToBeFormatted ).

ToString( formatString, provider );

else

return argToBeFormatted.ToString( );

}


// The formatting is handled here.

int digitIndex = 0;

long radix;

long longToBeFormatted;

long longPositive;

char[ ] outDigits = new char[ 63 ];

// Extract the radix from the format string.

formatString = formatString.Replace( radixCode, "" );

try

{

radix = Convert.ToInt64( formatString );

}

catch( Exception ex )

{

throw new ArgumentException( String.Format(

"The radix \"{0}\" is invalid.",

formatString ), ex );

}


// Verify that the radix is in the proper range.

if( radix <2 || radix > 36 )

throw new ArgumentException( String.Format(

"The radix \"{0}\" is not in the range 2..36.",

formatString ) );

// Verify that the argument can be converted to a long integer.

try

{

longToBeFormatted = (long)argToBeFormatted;

}

catch( Exception ex )

{

throw new ArgumentException( String.Format(

"The argument \"{0}\" cannot be " +

"converted to an integer value.",

argToBeFormatted ), ex );

}

// Extract the magnitude for conversion.

longPositive = Math.Abs( longToBeFormatted );


// Convert the magnitude to a digit string.

for( digitIndex = 0; digitIndex <= 64; digitIndex++ )

{

if( longPositive == 0 ) break;


outDigits[ outDigits.Length - digitIndex - 1 ] =

rDigits[ longPositive % radix ];

longPositive /= radix;

}

// Add a minus sign if the argument is negative.

if( longToBeFormatted < 0 )

outDigits[ outDigits.Length - digitIndex++ - 1 ] =

'-';


return new string( outDigits,

outDigits.Length - digitIndex, digitIndex );

}

}


class IFormatProviderDemo

{

static void ConvertToAnyRadix( object argToConvert,

string formatStr )

{

AnyRadix provider = new AnyRadix( );

string messageStr =

String.Format( "{{0:{0}}}", formatStr );


// Write the first part of the output line.

Console.Write( "{0,18} {1,-6}", argToConvert, formatStr );


// Convert the specified argument using the specified format.

try

{

Console.WriteLine( String.Format(

provider, messageStr, argToConvert ) );

}

catch( Exception ex )

{

// Display the exception without the stack trace.

int lineEnd = ex.ToString( ).IndexOf( '\n' );

Console.WriteLine( "{0}\n",

ex.ToString( ).Substring( 0, lineEnd ) );

}

}

static void Main( )

{

long twoToThe32 = 4294967296;

long fifteenNines = 999999999999999;

Console.WriteLine(

"This example of the IFormatProvider interface \n" +

"and the IFormatProvider.GetFormat( Type ) method " +

"\ngenerates the following output.\n" );

Console.WriteLine( "{0,18} Format Result", "Number" );

Console.WriteLine( "{0,18} ------ ------", "------" );

// These are valid conversions.

ConvertToAnyRadix( twoToThe32, "Ra2" );

ConvertToAnyRadix( twoToThe32, "Ra5" );

ConvertToAnyRadix( twoToThe32, "Ra16" );

ConvertToAnyRadix( twoToThe32, "Ra23" );

ConvertToAnyRadix( twoToThe32, "Ra36" );

ConvertToAnyRadix( fifteenNines, "Ra2" );

ConvertToAnyRadix( fifteenNines, "Ra3" );

ConvertToAnyRadix( fifteenNines, "Ra8" );

ConvertToAnyRadix( fifteenNines, "Ra11" );

ConvertToAnyRadix( fifteenNines, "Ra16" );

ConvertToAnyRadix( fifteenNines, "Ra23" );

ConvertToAnyRadix( fifteenNines, "Ra36" );

ConvertToAnyRadix( fifteenNines, "E16" );

ConvertToAnyRadix( fifteenNines, "" );

// These are error conditions.

ConvertToAnyRadix( fifteenNines, "Ra37" );

ConvertToAnyRadix( "ABCDEFGHIJKLM", "Ra16" );

}

}


/*

This example of the IFormatProvider interface

and the IFormatProvider.GetFormat( Type ) method

generates the following output.


Number Format Result

------ ------ ------

4294967296 Ra2 100000000000000000000000000000000

4294967296 Ra5 32244002423141

4294967296 Ra16 100000000

4294967296 Ra23 1606K7IC

4294967296 Ra36 1Z141Z4

999999999999999 Ra2 11100011010111111010100100110001100111111111111111

999999999999999 Ra3 11212010201001210101011021212000

999999999999999 Ra8 34327724461477777

999999999999999 Ra11 26A6A3689065639

999999999999999 Ra16 38D7EA4C67FFF

999999999999999 Ra23 1134DIFHLMM4

999999999999999 Ra36 9UGXNORJLR

999999999999999 E16 9.9999999999999900E+014

999999999999999 999999999999999

999999999999999 Ra37 System.ArgumentException: The radix "37" is not in th

e range 2..36.


ABCDEFGHIJKLM Ra16 System.ArgumentException: The argument "ABCDEFGHIJKLM

" cannot be converted to an integer value. ---> System.InvalidCastException: Sp

ecified cast is not valid.

*/


C++ 

复制代码

// Sample for the IFormatProvider interface and

// the IFormatProvider::GetFormat( Type* ) method.

using namespace System;


// This class implements the "Ra" formatting code. An instance of this

// class should be passed to methods requiring an IFormatProvider.

ref class AnyRadix: public IFormatProvider, public ICustomFormatter

{

private:

static Object^ null = nullptr;


// The value to be formatted is returned as a signed string

// of digits from the rDigits array.

static String^ radixCode = "Ra";

static array<Char>^rDigits = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};


public:


// This method returns an object that implements ICustomFormatter

// to do the formatting.

virtual Object^ GetFormat( Type^ argType )

{

// Here, the same object (this) is returned, but it would

// be possible to return an object of a different type.

if ( argType == ICustomFormatter::typeid )

return this;

else

return null;

}



// This method does the formatting only if it recognizes the

// format codes.

virtual String^ Format( String^ formatString, Object^ argToBeFormatted, IFormatProvider^ provider )

{

// If no format string is provided or the format string cannot

// be handled, use IFormattable or standard string processing.

if ( formatString == null || !formatString->Trim()->StartsWith( radixCode ) )

{

if ( dynamic_cast<IFormattable^>(argToBeFormatted) != nullptr )

return static_cast<IFormattable^>(argToBeFormatted)->ToString( formatString, provider );

else

return argToBeFormatted->ToString();

}


// The formatting is handled here.

int digitIndex = 0;

__int64 radix;

__int64 longToBeFormatted;

__int64 longPositive;

array<Char>^outDigits = gcnew array<Char>(64);

// Extract the radix from the format string.

formatString = formatString->Replace( radixCode, "" );

try

{

radix = Convert::ToInt64( formatString );

}

catch ( Exception^ ex )

{

throw gcnew ArgumentException( String::Format( "The radix \"{0}\" is invalid.\n", formatString ),ex );

}


// Verify that the radix is in the proper range.

if ( radix < 2 || radix > 36 )

throw gcnew ArgumentException( String::Format( "The radix \"{0}\" is not in the range 2..36.", formatString ) );


// Verify that the argument can be converted to a long integer.

try

{

longToBeFormatted = *static_cast<__int64^>(argToBeFormatted);

}

catch ( Exception^ ex )

{

throw gcnew ArgumentException( String::Format( "The argument \"{0}\" cannot be "

"converted to an integer value.", argToBeFormatted ),ex );

}


// Extract the magnitude for conversion.

longPositive = Math::Abs( longToBeFormatted );

// Convert the magnitude to a digit string.

for ( digitIndex = 0; longPositive != 0 && digitIndex <= 64; digitIndex++ )

{

outDigits[ outDigits->Length - digitIndex - 1 ] = rDigits[ longPositive % radix ];

longPositive /= radix;


}

// Add a minus sign if the argument is negative.

if ( longToBeFormatted < 0 )

outDigits[ outDigits->Length - digitIndex++ - 1 ] = '-';


return gcnew String( outDigits,outDigits->Length - digitIndex,digitIndex );

}


};


void ConvertToAnyRadix( Object^ argToConvert, String^ formatStr )

{

AnyRadix^ provider = gcnew AnyRadix;

String^ messageStr = String::Format( "{{0:{0}}}", formatStr );

// Write the first part of the output line.

Console::Write( "{0,18} {1,-6}", argToConvert, formatStr );

// Convert the specified argument using the specified format.

try

{

array<Object^>^argArray = {argToConvert};

Console::WriteLine( String::Format( provider, messageStr, argArray ) );

}

catch ( Exception^ ex )

{

// Display the exception without the stack trace.

int lineEnd = ex->ToString()->IndexOf( '\n' );

Console::WriteLine( "{0}\n", ex->ToString()->Substring( 0, lineEnd ) );

}


}


int main()

{

__int64 twoToThe32 = 4294967296;

__int64 fifteenNines = 999999999999999;

Console::WriteLine( "This example of the IFormatProvider interface \n"

"and the IFormatProvider::GetFormat( Type* ) method "

"\ngenerates the following output.\n" );

Console::WriteLine( "{0,18} Format Result", "Number" );

Console::WriteLine( "{0,18} ------ ------", "------" );

// These are valid conversions.

ConvertToAnyRadix( twoToThe32, "Ra2" );

ConvertToAnyRadix( twoToThe32, "Ra5" );

ConvertToAnyRadix( twoToThe32, "Ra16" );

ConvertToAnyRadix( twoToThe32, "Ra23" );

ConvertToAnyRadix( twoToThe32, "Ra36" );

ConvertToAnyRadix( fifteenNines, "Ra2" );

ConvertToAnyRadix( fifteenNines, "Ra3" );

ConvertToAnyRadix( fifteenNines, "Ra8" );

ConvertToAnyRadix( fifteenNines, "Ra11" );

ConvertToAnyRadix( fifteenNines, "Ra16" );

ConvertToAnyRadix( fifteenNines, "Ra23" );

ConvertToAnyRadix( fifteenNines, "Ra36" );

ConvertToAnyRadix( fifteenNines, "E16" );

ConvertToAnyRadix( fifteenNines, "" );

// These are error conditions.

ConvertToAnyRadix( fifteenNines, "Ra37" );

ConvertToAnyRadix( "ABCDEFGHIJKLM", "Ra16" );

}


/*

This example of the IFormatProvider interface

and the IFormatProvider::GetFormat( Type* ) method

generates the following output.


Number Format Result

------ ------ ------

4294967296 Ra2 100000000000000000000000000000000

4294967296 Ra5 32244002423141

4294967296 Ra16 100000000

4294967296 Ra23 1606K7IC

4294967296 Ra36 1Z141Z4

999999999999999 Ra2 11100011010111111010100100110001100111111111111111

999999999999999 Ra3 11212010201001210101011021212000

999999999999999 Ra8 34327724461477777

999999999999999 Ra11 26A6A3689065639

999999999999999 Ra16 38D7EA4C67FFF

999999999999999 Ra23 1134DIFHLMM4

999999999999999 Ra36 9UGXNORJLR

999999999999999 E16 9.9999999999999900E+014

999999999999999 999999999999999

999999999999999 Ra37 System.ArgumentException: The radix "37" is not in th

e range 2..36.


ABCDEFGHIJKLM Ra16 System.ArgumentException: The argument "ABCDEFGHIJKLM

" cannot be converted to an integer value. ---> System.InvalidCastException: Sp

ecified cast is not valid.

*/


J# 

复制代码

// Sample for the IFormatProvider interface and

// the IFormatProvider.GetFormat( Type ) method.

import System.*;


// This class implements the "Ra" formatting code. An instance of this

// class should be passed to methods requiring an IFormatProvider.

public class AnyRadix implements ICustomFormatter,IFormatProvider

{

// The value to be formatted is returned as a signed string

// of digits from the rDigits array.

private String radixCode = "Ra";

private static char rDigits[] = {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',

'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',

'U', 'V', 'W', 'X', 'Y', 'Z' };

// This method returns an object that implements ICustomFormatter

// to do the formatting.

public Object GetFormat(Type argType)

{

// Here, the same object (this) is returned, but it would

// be possible to return an object of a different type.

if ( argType.Equals(ICustomFormatter.class.ToType()) ) {

return this ;

}

else {

return null ;

}

} //GetFormat

// This method does the formatting only if it recognizes the

// format codes.

public String Format(String formatString, Object argToBeFormatted,

IFormatProvider provider)

{

// If no format string is provided or the format string cannot

// be handled, use IFormattable or standard string processing.

if(formatString == null||!(formatString.Trim().StartsWith(radixCode))) {

if ( argToBeFormatted instanceof IFormattable ) {

return((IFormattable)(argToBeFormatted)).

ToString(formatString,provider);

}

else {

return argToBeFormatted.ToString();

}

}


// The formatting is handled here.

int digitIndex = 0;

long radix;

long longToBeFormatted;

long longPositive;

char outDigits[] = new char[63];

// Extract the radix from the format string.

formatString = formatString.Replace(radixCode, "");

try {

radix = Convert.ToInt64(formatString);

}

catch(System.Exception ex) {

throw new ArgumentException(String.Format(

"The radix \"{0}\" is invalid.", formatString), ex);

}

// Verify that the radix is in the proper range.

if ( radix < 2 || radix > 36 ) {

throw new ArgumentException(String.Format(

"The radix \"{0}\" is not in the range 2..36.", formatString));

}

// Verify that the argument can be converted to a long integer.

try {

longToBeFormatted =(long)System.Convert.ToUInt64(argToBeFormatted);

}

catch(System.Exception ex) {

throw new ArgumentException(String.Format(

"The argument \"{0}\" cannot be "

+ "converted to an integer value.", argToBeFormatted), ex);

}

// Extract the magnitude for conversion.

longPositive = System.Math.Abs(longToBeFormatted);


// Convert the magnitude to a digit string.

for(digitIndex = 0;digitIndex <= 64;digitIndex++) {

if ( longPositive == 0 ) {

break ;

}

outDigits[outDigits.length - digitIndex - 1] =

rDigits[(int)(longPositive % radix)];

longPositive /= radix;

}

// Add a minus sign if the argument is negative.

if ( longToBeFormatted < 0 ) {

outDigits [outDigits.length - digitIndex ++ - 1] = '-';

}

return new String(outDigits, outDigits.length - digitIndex, digitIndex);

} //Format

} //AnyRadix


class IFormatProviderDemo

{

static void ConvertToAnyRadix(Object argToConvert, String formatStr)

{

AnyRadix provider = new AnyRadix();

String messageStr = String.Format("{{0:{0}}}", formatStr);

// Write the first part of the output line.

Console.Write("{0,18} {1,-6}", argToConvert, formatStr);

// Convert the specified argument using the specified format.

try {

Console.WriteLine(String.Format((IFormatProvider)provider,

messageStr,new Object[]{ argToConvert}));

}

catch(System.Exception ex) {

// Display the exception without the stack trace.

int lineEnd = ex.ToString().IndexOf('\n');

Console.WriteLine("{0}\n", ex.ToString().Substring(0, lineEnd));

}

} //ConvertToAnyRadix

public static void main(String[] args)

{

long twoToThe32 = 4294967296L;

long fifteenNines = 999999999999999L;


Console.WriteLine(("This example of the IFormatProvider interface \n"

+ "and the IFormatProvider.GetFormat( Type ) method "

+ "\ngenerates the following output.\n"));

Console.WriteLine("{0,18} Format Result", "Number");

Console.WriteLine("{0,18} ------ ------", "------");


// These are valid conversions.

ConvertToAnyRadix(((System.UInt64 )(twoToThe32)), "Ra2");

ConvertToAnyRadix(((System.UInt64)(twoToThe32)), "Ra5");

ConvertToAnyRadix(((System.UInt64)(twoToThe32)), "Ra16");

ConvertToAnyRadix(((System.UInt64)(twoToThe32)), "Ra23");

ConvertToAnyRadix(((System.UInt64)(twoToThe32)), "Ra36");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra2");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra3");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra8");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra11");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra16");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra23");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra36");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "E16");

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "");


// These are error conditions.

ConvertToAnyRadix(((System.UInt64)(fifteenNines)), "Ra37");

ConvertToAnyRadix("ABCDEFGHIJKLM", "Ra16");

} //main

} //IFormatProviderDemo


/*

This example of the IFormatProvider interface

and the IFormatProvider.GetFormat( Type ) method

generates the following output.


Number Format Result

------ ------ ------

4294967296 Ra2 100000000000000000000000000000000

4294967296 Ra5 32244002423141

4294967296 Ra16 100000000

4294967296 Ra23 1606K7IC

4294967296 Ra36 1Z141Z4

999999999999999 Ra2 11100011010111111010100100110001100111111111111111

999999999999999 Ra3 11212010201001210101011021212000

999999999999999 Ra8 34327724461477777

999999999999999 Ra11 26A6A3689065639

999999999999999 Ra16 38D7EA4C67FFF

999999999999999 Ra23 1134DIFHLMM4

999999999999999 Ra36 9UGXNORJLR

999999999999999 E16 9.9999999999999900E+014

999999999999999 999999999999999

999999999999999 Ra37 System.ArgumentException: The radix "37" is not in th

e range 2..36.


ABCDEFGHIJKLM Ra16 System.ArgumentException: The argument "ABCDEFGHIJKLM"

cannot be converted to an integer value. ---> System.FormatException: Input str

ing was not in a correct format.

*/



九、ICustomFormatter 接口

定义一种方法,它支持对象值的自定义(用户定义)格式设置。

命名空间:System
程序集:mscorlib(在 mscorlib.dll 中)

语法


C#

[ComVisibleAttribute(true)]

public interface ICustomFormatter


备注

当此接口由引用或值类型实现时,Format 方法会返回对象值的自定义格式字符串表示形式。

使用此接口和 IFormatProvider 接口可取代在 .NET Framework 格式设置方法中提供的支持,这些方法接受 IFormatProvider 参数。例如,使用此接口可提供由 String.Format Int32.ToString 方法进行的对象值自定义格式设置。

派生一个类,它实现 IFormatProvider 接口及其 GetFormat 方法。为要取代的方法的 IFormatProvider 参数指定该派生类。您的 GetFormat 方法实现应返回一个格式对象,它实现 ICustomFormatter 接口。然后,.NET Framework 方法将使用您的自定义格式设置来替代它自己的格式设置。



友情链接

郑州大学软件学院 SpringWidgets-Blogger 徵信社 翻译公司 链接帮手网 行驶证字体 酷站目录 Friend Connectified