String.Format - как это работает и как реализовать собственные строки форматирования


79

String.Format()Например, с его помощью можно форматировать DateTimeобъекты множеством различных способов. Каждый раз, когда я ищу желаемый формат, мне нужно поискать в Интернете. Почти всегда я нахожу пример, который могу использовать. Например:

String.Format("{0:MM/dd/yyyy}", DateTime.Now);          // "09/05/2012"

Но я понятия не имею, как это работает и какие классы поддерживают эти «волшебные» дополнительные строки.

Итак, мои вопросы:

  1. Как String.Formatсопоставлять дополнительную информацию MM/dd/yyyyсо строковым результатом?
  2. Все ли объекты Microsoft поддерживают эту функцию?
    Это где-то задокументировано?
  3. Можно ли сделать что-то подобное:
    String.Format("{0:MyCustomFormat}", new MyOwnClass())

Вы можете взглянуть на этот codeproject.com/Articles/6533/Custom-String-Formatting-in-NET
V4Vendetta

Ответы:


88

String.Formatсопоставляет каждый из токенов внутри строки (и {0}т. д.) с соответствующим объектом: http://msdn.microsoft.com/en-us/library/system.string.format.aspx

Необязательно предоставляется строка формата:

{ index[,alignment][ : formatString] }

Если formatStringпредоставляется, соответствующий объект должен реализовывать IFormattable и, в частности, ToStringметод, который принимает formatStringи возвращает соответствующую отформатированную строку: http://msdn.microsoft.com/en-us/library/system.iformattable.tostring.aspx

Также IFormatProviderможет использоваться, который может использоваться для захвата основных стандартов форматирования / значений по умолчанию и т. Д. Примеры здесь и здесь .

Итак, ответы на ваши вопросы по порядку:

  1. Он использует IFormattableинтерфейс ToString()метод на DateTimeобъекте и передает его в MM/dd/yyyyстроке формата. Это та реализация, которая возвращает правильную строку.

  2. Любой реализующий объект IFormattableподдерживает эту функцию. Вы даже можете написать свой собственный!

  3. Да, смотрите выше.


11
+1 за ссылку на документацию . «Искать в Интернете» можно. Но когда вам нужно более глубокое понимание, вам следует прочитать Руководство.
MarkJ

Хороший ответ, но можете ли вы сказать мне, где я могу найти для каждого класса, который реализует IFormattable, где я могу найти разрешенные строки формата. Например DateTime поддерживает (над моей головой) y M d h m sи многое другое. Числовые типы поддерживаются в Cвалюте, но это не все, что я знаю из поиска по arround, а не из документации Microsoft.
hwcverwe

@hwcverwe - почти любой поиск Google помещает документацию MSDN в начало или ближе к началу поиска любого объекта. Не будет отдельной страницы, которая показывает ToString (...) для каждого объекта - их потенциально может быть «бесконечное» количество, потому что по умолчанию все объекты реализуют по крайней мере ToString (), хотя не обязательно ToString (формат).
Вонко Разумный


20

Насколько я понимаю, вам нужно будет реализовать IFormattable в своем классе для поддержки этого. Затем у него есть метод ToString, который принимает параметры, которые вы передаете в String.Format.

Вот пример.

// Define other methods and classes here
public class Sample : IFormattable
{
     public string ToString(string format, IFormatProvider provider)
     {
         return String.Concat("Your custom format was ", format);
     }
}

String.Format("{0:MyCustomFormat}", new Sample())

5
  1. Ознакомьтесь с официальными документами MSDN, здесь есть полный список строк формата DateTime: http://msdn.microsoft.com/en-us/library/az4se3k1.aspx . «Волшебных» струн действительно немало.

  2. Насколько я знаю, не все типы имеют "интересное" форматирование, но все типы поддерживаются ToString(). Если вам нужно отформатировать встроенный объект, вы можете добавить для этого метод расширения, но обычно форматирование предоставляется в любом месте, где оно необходимо (или, другими словами, я написал только собственные средства форматирования для своих типов) .

  3. Да, вы можете написать свои собственные, и если у вас есть данные, которые можно форматировать по-разному, вам, вероятно, следует написать собственный форматировщик, реализовав IFormattable, снова см. Документы здесь: http://msdn.microsoft.com/en-us/ библиотека / system.iformattable.aspx . Это довольно просто, вы просто проверяете предоставленные строки и записываете свои данные на их основе, за кулисами нет никакой магии :-)


4

Под обложками String.Format делает следующее:

IFormattable formattable = objectToFormat as IFormattable;
if (formattable != null)
{
    formattable.ToString(objectToFormat);
}
else
{
    objectToFormat.ToString();
}

По вашим вопросам,

  1. Как String.Format сопоставляет дополнительную информацию MM / dd / yyyy со строковым результатом?

    Как указано выше, он просто вызывает IFormattable .ToString (строковый формат, поставщик IFormatProvider). Провайдер часто говорит вам, какова культура вашей системы. Часто null, потому что люди не передают его String.Format (), как вы это делали в вашем случае.

  2. Все ли объекты Microsoft поддерживают эту функцию? Это где-то задокументировано?

    Все, что реализует IFormattable, делает.

  3. Можно ли сделать что-то подобное: String.Format("{0:MyCustomFormat}, new MyOwnClass())

    По сути, если вы хотите, чтобы ваш собственный объект что-то делал с предоставленным вами форматом IFormattable.

Существует огромное количество поддерживающих классов и перечислителей, чтобы гарантировать, что строки формата во многом схожи. Подробнее здесь .


0

Да, это возможно - это можно полностью настроить. Посмотрите эту ссылку на документацию о настраиваемом форматировании даты и времени.

Если у вас есть собственный объект, вы должны переопределить ToString()метод и вывести то, что вы считаете подходящим представлением. Как только вы это сделаете, вы можете использовать, String.Format("{0:MyCustomFormat}", new MyOwnClass())потому что это неявно вызываетMyOwnClass.ToString()


-1 - OP спрашивает не только о DateTimeформатировании. И просто ссылка - это не ответ.
Одед

1
Очень жестко. DateTime - один из аспектов, и я расширял свой ответ, пока вы проголосовали против.
Maciej

6
Развернуть ответ затем пост , и вы не получите downvoted.
Одед

0

Документацию по датам можно найти здесь: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

Это должно точно сказать вам, что означают все символы форматирования даты, такие как MM.

Если вы хотите изменить способ вывода строки для настраиваемого класса, вы можете переопределить метод ToString, например:

public class User
{
     public string Name { get; set; }
     public int Age { get; set; }

     public override string ToString()
     {
         return this.Name + " is " + this.Age + " years old.";
     }
}

а затем вы можете просто сделать что-то вроде myUser.ToString()и получить указанный вами результат.


0

И чтобы ответить на ваш третий вопрос: это невозможно с этим синтаксисом, но вы можете предоставить экземпляры IFormatProviderи ICustomFormatterдля типа, который вы не создавали или не реализовывали IFormattableвнутри своего типа (хотя в основном это расширяется ToString).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.