String.Format - jak to działa i jak wdrażać niestandardowe ciągi formatujące


79

Dzięki String.Format()temu można np. Formatować DateTimeobiekty na wiele różnych sposobów. Za każdym razem, gdy szukam żądanego formatu, muszę przeszukać Internet. Prawie zawsze znajduję przykład, którego mogę użyć. Na przykład:

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

Ale nie mam pojęcia, jak to działa i które klasy obsługują te „magiczne” dodatkowe ciągi.

Więc moje pytania to:

  1. Jak zamapuje String.Formatdodatkowe informacje MM/dd/yyyyna wynik w postaci ciągu?
  2. Czy wszystkie obiekty firmy Microsoft obsługują tę funkcję?
    Czy jest to gdzieś udokumentowane?
  3. Czy można zrobić coś takiego:
    String.Format("{0:MyCustomFormat}", new MyOwnClass())

Możesz rzucić
V4Vendetta

Odpowiedzi:


88

String.Formatdopasowuje każdy z tokenów w ciągu ( {0}itp.) do odpowiedniego obiektu: http://msdn.microsoft.com/en-us/library/system.string.format.aspx

Opcjonalnie dostępny jest ciąg formatu:

{ index[,alignment][ : formatString] }

Jeśli formatStringjest podany, odpowiedni obiekt musi implementować IFormattable, a konkretnie ToStringmetodę, która akceptuje formatStringi zwraca odpowiedni sformatowany ciąg: http://msdn.microsoft.com/en-us/library/system.iformattable.tostring.aspx

IFormatProviderMożna również stosować, które mogą być wykorzystywane do przechwytywania podstawowe formatowanie standardy / domyślne itd. Przykłady tutaj i tutaj .

A więc odpowiedzi na Twoje pytania w kolejności:

  1. Używa metody IFormattableinterfejsu ToString()na DateTimeobiekcie i przekazuje ten MM/dd/yyyyciąg formatu. To jest ta implementacja, która zwraca poprawny ciąg.

  2. Każdy obiekt, który implementuje, IFormattableobsługuje tę funkcję. Możesz nawet napisać własne!

  3. Tak, patrz wyżej.


11
+1 za link do dokumentacji . „Wyszukiwanie w Internecie” może być OK. Ale kiedy potrzebujesz głębszego zrozumienia, powinieneś przeczytać podręcznik.
MarkJ

Dobra odpowiedź, ale czy możesz mi powiedzieć, gdzie mogę znaleźć dla każdej klasy implementującej IFormattable, gdzie mogę znaleźć dozwolone formatStrings. Na przykład obsługuje DateTime (na czele) y M d h m si nie tylko. Typy nummeric obsługują Cz waluty, ale to nie wszystko, co wiem z wyszukiwania w okolicy, a nie z przeglądania dokumentacji Microsoft.
hwcverwe

@hwcverwe - prawie każda wyszukiwarka Google umieści dokumentację MSDN na początku wyszukiwania dowolnego obiektu. Nie będzie jednej strony pokazującej ToString (...) dla każdego obiektu - jest ich potencjalnie „nieskończona” ilość, ponieważ domyślnie wszystkie obiekty implementują co najmniej ToString (), chociaż niekoniecznie ToString (format).
Wonko the Sane


20

Z mojego punktu widzenia, aby to obsługiwać, musisz zaimplementować IFormattable w swojej klasie. To ma następnie metodę ToString, która przyjmuje parametry przekazane do String.Format.

Oto przykład.

// 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. Sprawdź oficjalną dokumentację MSDN, pełna lista ciągów formatu DateTime znajduje się tutaj: http://msdn.microsoft.com/en-us/library/az4se3k1.aspx . Rzeczywiście istnieje kilka „magicznych” strun.

  2. O ile wiem, nie wszystkie typy mają „interesujące” formatowanie, ale wszystkie je obsługują ToString(). Jeśli potrzebujesz sformatować wbudowany obiekt, możesz dodać metodę rozszerzenia, aby to zrobić, ale zwykle formatowanie jest dostarczane w dowolnym miejscu, w którym jest potrzebne (lub inaczej, napisałem tylko niestandardowe elementy formatujące dla moich własnych typów) .

  3. Tak, możesz napisać własne, a jeśli masz dane, które można sformatować na różne sposoby, prawdopodobnie powinieneś napisać niestandardowy program formatujący, implementując IFormattable, ponownie zapoznaj się z dokumentacją tutaj: http://msdn.microsoft.com/en-us/ biblioteka / system.iformattable.aspx . To dość proste, wystarczy sprawdzić podane ciągi znaków i na ich podstawie wypisać dane, za kulisami nie ma magii :-)


4

Pod okładkami String.Format robi coś w następujący sposób,

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

W przypadku pytań

  1. W jaki sposób String.Format mapuje dodatkowe informacje MM / dd / rrrr na wynik w postaci łańcucha?

    Jak określono powyżej, po prostu wywołuje IFormattable .ToString (format ciągu, dostawca IFormatProvider). Dostawca jest często kimś, kto mówi ci, jaka jest kultura twojego systemu. Często null, ponieważ ludzie nie przekazują tego String.Format (), tak jak w Twoim przypadku.

  2. Czy wszystkie obiekty Microsoft obsługują tę funkcję? Czy jest to gdzieś udokumentowane?

    Wszystko, co implementuje IFormattable, robi.

  3. Czy można zrobić coś takiego: String.Format("{0:MyCustomFormat}, new MyOwnClass())

    Zasadniczo, jeśli chcesz, aby Twój własny obiekt robił coś z dostarczonym przez Ciebie formatem IFormattable.

Istnieje ogromna liczba klas pomocniczych i modułów wyliczających, które zapewniają, że ciągi formatujące są w dużej mierze podobne. Więcej tutaj .


0

Tak, jest to możliwe - można go całkowicie dostosować. Spójrz na to łącze do dokumentacji dotyczące niestandardowego formatowania daty i godziny.

Jeśli masz swój własny obiekt, to od ciebie zależy, czy zmienisz ToString()metodę i wyprowadzisz wszystko, co uważasz za odpowiednią reprezentację. Gdy to zrobisz, możesz użyć, String.Format("{0:MyCustomFormat}", new MyOwnClass())ponieważ to niejawnie wywołujeMyOwnClass.ToString()


-1 - OP pyta o coś więcej niż tylko o DateTimeformatowanie. Sam link nie jest odpowiedzią.
Odedł

1
Bardzo ostra. DateTime jest jednym z aspektów i rozszerzałem moją odpowiedź, podczas gdy ty przegłosowałeś.
Maciej

6
Rozwiń odpowiedź, a następnie opublikuj , a nie zostaniesz odrzucony.
Oded

0

Dokumentację dotyczącą dat można znaleźć tutaj: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

To powinno dokładnie powiedzieć, co oznaczają wszystkie znaki formatujące datę, takie jak MM.

Jeśli chcesz zmienić sposób wyprowadzania ciągu dla klasy niestandardowej, możesz zastąpić metodę ToString, na przykład:

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.";
     }
}

a następnie możesz po prostu zrobić coś podobnego myUser.ToString()i uzyskać określone wyjście.


0

Odpowiadając na trzecie pytanie: nie jest to możliwe przy tej składni, ale możesz podać wystąpienia IFormatProvideri ICustomFormatterdla typu, którego nie utworzyłeś, lub zaimplementować IFormattablew swoim typie (chociaż to zasadniczo się rozszerza ToString).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.