Примеры строкового форматирования в пользовательских типах

Давайте рассмотрим другой пример использования знаменитого типа Complex. На этот раз попробуем реализовать IFormattable, чтобы сделать его несколько более удобным для генерации строковой версии экземпляра.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Text;
using System.Globalization;
public struct Complex : IFormattable {
public Complex( double real, double imaginary )  {
this.real = real;
this.imaginary = imaginary;
}
// Реализация IFormattable
public string ToString( string format,
IFormatProvider formatProvider )  {
StringBuilder sb = new StringBuilder();
if ( format == "DBG" )  {
// Генерация отладочного вывода для данного объекта
sb.Append( this.GetType () .ToString() + "\n" );
sb.AppendFormat ( "действительная:\t { 0 }\n", real );
sb. AppendFormat ( "мнимая: \t { 0 } \n", imaginary );
} else {
sb.Append( " ( " ) ;
sb.Append( real.ToString(format, formatProvider)  );
sb.Append( " : " );
sb.Append( imaginary.ToString(format, formatProvider)  );
sb.Append( " ) " ) ;
}
return sb.ToString();
}
private double real;
private double imaginary;
}
public class EntryPoint
static void Main() {
Culturelnfo local = Culturelnfo.CurrentCulture;
Culturelnfo germany = new Culturelnfo( "de-DE" );
Complex cpx = new Complex( 12.3456, 1234.56 );
string strCpx = cpx.ToString( "F", local );
Console.WriteLine( strCpx );
strCpx = cpx.ToString( "F", germany );
Console.WriteLine( strCpx );
Console.WriteLine ( "nОтладочный вывод:\n{0:DBG}", cpx );
}

Основной код этого примера сосредоточен внутри реализации IFormattable.ToString. Для данного типа реализована форматная строка “DBG”, которая создает строку, отображающую внутреннее состояние объекта, и которая может пригодиться в целях отладки.

Понятно, что можно предоставить и больше информации об экземпляре для вывода в журнал отладки, но идея должна быть ясна.

Если форматная строка не равна “DBG”, то просто выполняется обращение к реализации IFormattable типа System. Double. Обратите внимание на применение StringBuilder для создания строки, возвращаемой в конечном итоге.

Также было решено использовать метод Console.WriteLine и его синтаксис формата экземпляра для отладочного вывода на консоль — просто, чтобы продемонстрировать разнообразие применения.

ICustomFormatter

ICustomFormatter — это интерфейс, позволяющий заменять или расширять встроенный или существующий интерфейс IFormattable объекта.

Всякий раз, когда вызывается String.Format или StringBuilder.AppendFormat для преобразования экземпляра объекта в строку, перед тем, как произойдет вызов через реализацию IFormattable.ToString объекта или Object.ToString, если интерфейс IFormattable не реализован, сначала выполняется проверка, не предоставляет ли переданный IFormatProvider собственного средства форматирования.

Если предоставляет, то вызывается IFormatProvider.GetFormat с передачей типа ICustomFormatter. Если возвращается реализация ICustomFormatter, то метод использует ее. В противном случае он использует реализацию IFormattable.TiString самого объекта или же реализацию Object.ToString, если объект не реализует IFormattable.

Рассмотрим следующий пример, где снова продолжается предыдущий пример Complex, но на этот раз расширяются возможности отладочного вывода вне структуры Complex. Измененный код выделен полужирным.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System;
using System.Text;
using System.Globalization;
public class ComplexDbgFormatter : ICustomFormatter, IFormatProvider
{
// Реализация IFormatProvider
public object GetFormat ( Type formatType ) {
if ( formatType == typeof (ICustomFormatter) ) {
return this;
} else {
return Culturelnfo.CurrentCulture. GetFormat ( formatType ) ;
// реализация icustomformatter public string format( string format, object arg,
iformatprovider formatprovider ) {
if ( arg.gettype() == typeof(complex) && format == "dbg" ) {
complex cpx « (complex) arg;
// сгенерировать отладочный вывод для данного объекта
stringbuilder sb = new stringbuilder();
sb.append( arg.gettype().tostring() + "\n" );
sb.appendformat( "\действительная:\t{0}\n", cpx.real ) ;
sb.appendformat( "\мнимая:\t{0}\n", cpx.imaginary ) ;
return sb.tostring();
} else {
iformattable formattable = arg as iformattable;
if ( formattable != null ) {
return formattable.tostring( format, formatprovider ) ;
} else {
return arg.tostring();
}
public struct Complex : IFormattable {
public Complex ( double real, double imaginary )  {
this.real = real;
this.imaginary = imaginary;
}
public double real {
get {
return real; }
}
public double imaginary {
get {
return imaginary; }
}
// Реализация IFormattable
public string ToString ( string format,
IFormatProvider formatProvider )  {
StringBuilder sb = new StringBuilder();
sb.Append( " ( " ) ;
sb.Append( real.ToString(format, formatProvider)  );
sb.Append( " : " ) ;
sb.Append( imaginary.ToString(format, formatProvider) );
sb.Append ( " ) " ) ;
return sb.ToString ();
}
private double real;
private double imaginary;
}
public class EntryPoint {
static void Main()  {
Culturelnfo local = Culturelnfo.CurrentCulture;
Culturelnfo germany = new Culturelnfo( "de-DE" );
Complex cpx = new Complex( 12.3456, 1234.56 );
string strCpx = cpx.ToString ( "F", local );
Console.WriteLine ( strCpx );
strCpx = cpx.ToString( "F", germany );
Console.WriteLine( strCpx );
complexdbgformatter dbgformatter =
new complexdbgformatter () ;
strcpx = string.format( dbgformatter, "{0:dbg}", cpx ) ;
console.writeline ( " \n отладочмый вывод: \n{0}" , strcpx ) ;
}

Конечно, приведенный пример немного сложнее. Но если вы не являетесь автором типа Complex, то это может быть единственным способом обеспечить специальное форматирование для данного типа. Применяя этот прием, можно предоставлять пользовательское форматирование любому из встроенных типов системы.

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100