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())

Ви можете подивитися цей кодproject.com
Articles/

Відповіді:


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, де я можу знайти дозволений formatStrings. Наприклад, підтримка DateTime (на моїй голові) y M d h m sта багато іншого. Числові типи підтримує Cвалюта, але це не все, що я знаю, шукаючи навколо, а не переглядаючи документацію 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). Постачальник послуг часто говорить про те, яка культура вашої системи. Часто нульовий, оскільки люди не передають його String.Format (), як це було у вашому випадку.

  2. Чи всі об’єкти Microsoft підтримують цю функцію? Це десь задокументовано?

    Все, що реалізує IFormattable, робить.

  3. Чи можна зробити щось подібне: String.Format("{0:MyCustomFormat}, new MyOwnClass())

    По суті, якщо ви хочете, щоб ваш власний об’єкт робив щось із запропонованим вами форматом IFormattable.

Існує величезна кількість підтримуючих класів та перечислювачів, щоб переконатися, що рядки форматування значною мірою схожі. Більше тут .


0

Так, це можливо - це можна повністю налаштувати. Подивіться це посилання на документацію щодо користувацького форматування дати та часу.

Якщо у вас є власний об’єкт, вам потрібно перевизначити ToString()метод і вивести все, що, на вашу думку, є відповідним поданням. Після цього ви можете використовувати, String.Format("{0:MyCustomFormat}", new MyOwnClass())оскільки це неявно викликаєMyOwnClass.ToString()


-1 - ОП запитує більше, ніж DateTimeформатування. І просто посилання - це не відповідь.
Початок подій

1
Дуже суворий. DateTime - один із аспектів, і я розширював свою відповідь, поки ви проголосували.
Мацей

6
Розгорніть відповідь, а потім опублікуйте , і ви не отримаєте голосу проти.
Почав відбуватися

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.