常规的调用ToString()方法,存在两个问题.
(1)、调用者无法控制字符串的格式
(2)、调用者不能方便的选择一种特定的语言文化来格式化字符串.
在开发一些国际化的应用时,应用程序需要调用与当前线程不同的语言文化来格式化字符串.
so,为了对字符串进行更多的控制,你重写的的ToString()方法应该允许指定具体的格式和语言文化信息.
为了能使调用者在调用对象实例的ToString()方法的时候,选择格式和语言文化,该对象应该实现System.IFormattable接口,接口代码如下:
// // 摘要: // 提供一种功能,用以将对象的值格式化为字符串表示形式。 [ComVisible(true)] public interface IFormattable { // // 摘要: // 使用指定格式对当前实例的值设置格式。 // // 参数: // format: // 要使用的格式。 - 或 - null 引用(在 Visual Basic 中为 Nothing),用于使用为 System.IFormattable 实现的类型定义的默认格式。 // // formatProvider: // 要用于对值设置格式的提供程序。 - 或 - null 引用(在 Visual Basic 中为 Nothing),用于从操作系统的当前区域设置获取数字格式信息。 // // 返回结果: // 采用指定格式的当前实例的值。 string ToString(string format, IFormatProvider formatProvider);
}
FCL(Framework Common Language)中的所有基类型(Byte,SByte,Int16/UInt16,Int32/Uint32,Int64/Uint64,Single,Double,Decimal和Datetime)都实现了这个接口,这些基类型调用ToString方法之后,返回的都是字面值的字符串形式,此外FCL中还有一些类型实现了这个接口.
1、Guid,Guid的ToString代码如下所示:
public unsafe string ToString(string format, IFormatProvider provider) { string str; if ((format == null) || (format.Length == 0)) { format = "D"; } int offset = 0; bool flag = true; bool flag2 = false; if (format.Length != 1) { throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); } char ch = format[0]; switch (ch) { case 'D': case 'd': str = string.FastAllocateString(0x24); break; case 'N': case 'n': str = string.FastAllocateString(0x20); flag = false; break; case 'B': case 'b': str = string.FastAllocateString(0x26); fixed (char* str2 = ((char*) str)) { char* chPtr = str2; if (chPtr != null) { chPtr += RuntimeHelpers.OffsetToStringData; } chPtr[offset++] = '{'; chPtr[0x25] = '}'; } break; case 'P': case 'p': str = string.FastAllocateString(0x26); fixed (char* str3 = ((char*) str)) { char* chPtr2 = str3; if (chPtr2 != null) { chPtr2 += RuntimeHelpers.OffsetToStringData; } chPtr2[offset++] = '('; chPtr2[0x25] = ')'; } break; default: if ((ch != 'X') && (ch != 'x')) { throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); } str = string.FastAllocateString(0x44); fixed (char* str4 = ((char*) str)) { char* chPtr3 = str4; if (chPtr3 != null) { chPtr3 += RuntimeHelpers.OffsetToStringData; } chPtr3[offset++] = '{'; chPtr3[0x43] = '}'; } flag = false; flag2 = true; break; } fixed (char* str5 = ((char*) str)) { char* guidChars = str5; if (guidChars != null) { guidChars += RuntimeHelpers.OffsetToStringData; } if (flag2) { guidChars[offset++] = '0'; guidChars[offset++] = 'x'; offset = HexsToChars(guidChars, offset, this._a >> 0x18, this._a >> 0x10); offset = HexsToChars(guidChars, offset, this._a >> 8, this._a); guidChars[offset++] = ','; guidChars[offset++] = '0'; guidChars[offset++] = 'x'; offset = HexsToChars(guidChars, offset, this._b >> 8, this._b); guidChars[offset++] = ','; guidChars[offset++] = '0'; guidChars[offset++] = 'x'; offset = HexsToChars(guidChars, offset, this._c >> 8, this._c); guidChars[offset++] = ','; guidChars[offset++] = '{'; offset = HexsToChars(guidChars, offset, this._d, this._e, true); guidChars[offset++] = ','; offset = HexsToChars(guidChars, offset, this._f, this._g, true); guidChars[offset++] = ','; offset = HexsToChars(guidChars, offset, this._h, this._i, true); guidChars[offset++] = ','; offset = HexsToChars(guidChars, offset, this._j, this._k, true); guidChars[offset++] = '}'; } else { offset = HexsToChars(guidChars, offset, this._a >> 0x18, this._a >> 0x10); offset = HexsToChars(guidChars, offset, this._a >> 8, this._a); if (flag) { guidChars[offset++] = '-'; } offset = HexsToChars(guidChars, offset, this._b >> 8, this._b); if (flag) { guidChars[offset++] = '-'; } offset = HexsToChars(guidChars, offset, this._c >> 8, this._c); if (flag) { guidChars[offset++] = '-'; } offset = HexsToChars(guidChars, offset, this._d, this._e); if (flag) { guidChars[offset++] = '-'; } offset = HexsToChars(guidChars, offset, this._f, this._g); offset = HexsToChars(guidChars, offset, this._h, this._i); offset = HexsToChars(guidChars, offset, this._j, this._k); } } return str; }
调用代码如下:
var gid = Guid.NewGuid(); Console.WriteLine(gid.ToString("d")); Console.WriteLine(gid.ToString("n")); Console.WriteLine(gid.ToString("b")); Console.WriteLine(gid.ToString("p")); Console.WriteLine(gid.ToString("x"));
2、Enum,Enum重写的ToString()方法,ToString()方法没有使用到IFormatProvidedr接口,如下所示:
public string ToString(string format, IFormatProvider provider) => this.ToString(format);
public string ToString(string format) { if ((format == null) || (format.Length == 0)) { format = "G"; } if (string.Compare(format, "G", StringComparison.OrdinalIgnoreCase) == 0) { return this.ToString(); } if (string.Compare(format, "D", StringComparison.OrdinalIgnoreCase) == 0) { return this.GetValue().ToString(); } if (string.Compare(format, "X", StringComparison.OrdinalIgnoreCase) == 0) { return InternalFormattedHexString(this.GetValue()); } if (string.Compare(format, "F", StringComparison.OrdinalIgnoreCase) != 0) { throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification")); } return InternalFlagsFormat((RuntimeType) base.GetType(), this.GetValue()); }
调用代码如下:
static void Main(string[] args) { var a = Type.a; //返回常规的字符串,也就是a的字符串形式,输出:a Console.WriteLine(a.ToString("G")); //返回a的枚举值,输出:1 Console.WriteLine(a.ToString("D")); //返回a的十六进制表现形式,输出:00000001 Console.WriteLine(a.ToString("X")); //返回a的字符串形式,输出:a Console.WriteLine(a.ToString("F")); Console.ReadKey(); } enum Type { a = 1, b = 2, c = 3 }