2015-05-23 14 views
19

Mam pytanie o następującym kodzie:Console.WriteLine Podstawy

class CurrentDate 
    { 
     static void Main() 
     { 
      Console.WriteLine(DateTime.Now); 
     } 
    } 

Dokumentacja mówi:

pisze reprezentacji tekstowej określonej tablicy obiektów, następnie bieżącej linii terminatora , do standardowego strumienia wyjściowego przy użyciu określonej informacji o formacie.

Więc moje pytanie brzmi: Jak to się stało WriteLine zna reprezentacji tekstowej DateTime obiektu? Mam na myśli, że jeśli utworzę własny obiekt z mojej własnej klasy, jak on będzie wiedział, jak przekonwertować wartość na tekst? A nawet więcej, skąd wiadomo, jaka jest wartość? Jak zdefiniować "wartość" obiektu?

+0

Zobacz https://msdn.microsoft.com/en-gb/library/ms173154%28v=vs.80%29.aspx – adaam

+0

Uwaga: Inspektor obiektów Visual Studio Debugger również używa bardzo podobnego mechanizmu ('MyClass.toString '), aby dowiedzieć się, co wydrukować jako wartość, gdy obiekt jest wyświetlany jako pojedynczy wiersz. – Superbest

+0

'Console.WriteLine()' niejawnie wywołuje 'ToString()', więc dla twojego własnego obiektu musisz zaimplementować/przesłonić metodę 'ToString()'. – Jaider

Odpowiedz

17

Jak to możliwe, że WriteLine zna tekstową reprezentację obiektu DateTime? Mam na myśli, że jeśli utworzę własny obiekt z mojej własnej klasy, jak on będzie wiedział, jak przekonwertować wartość na tekst?

Console.WriteLine ma set of overloads dopasowywanie określonych typów (głównie prymitywy). Jeśli kompilator nie jest zgodny z przeciążeniem z podanym typem, pasuje do przeciążenia pobierającego System.Object (pod warunkiem, że podasz pojedynczy parametr). Jeśli tak się stanie, sprawdza, czy typ implementuje IFormattable, jeśli tak, wywołuje IFormattable.ToString(null, Formatter). Jeśli nie, wywołuje on ToString na twoim obiekcie. ToString jest zdefiniowany w System.Object, z której wszystkie obiekty dziedziczą.Każdy obiekt, który chce niestandardowej reprezentacji, zastępuje domyślne zachowanie, na przykład DateTime.

Na przykład, powiedzmy, że masz Foo klasy z właściwością Bar strun, a chcesz Console.WriteLine wydrukować coś sensownego, gdy przechodzi swój Foo do niego:

public class Foo 
{ 
    public string Bar { get; set; } 
    public override string ToString() 
    { 
     return Bar; 
    } 
} 

A teraz chcemy przekazać go Console.WriteLine :

public static void Main(string[] args) 
{ 
     var foo = new Foo { Bar = "bar" }; 
     Console.WriteLine(foo); 
} 

Przyniesie "pasek".

9

Ponieważ nie ma przeciążenia dla Console.WriteLine(DateTime), jak w przypadku przeciążenia Console.WriteLine(Object) nazywa i this overload callsTextWriter.WriteLine(object) overload który jest implemented as:

IFormattable f = value as IFormattable; 
if (f != null) 
    WriteLine(f.ToString(null, FormatProvider)); 
else 
    WriteLine(value.ToString()); 

Jak widać, metoda ta sprawdza, czy tego typu obiekt implementuje IFormattable interface lub nie. Od Datetime implements this interface zostanie wywołany Twój f.ToString(null, FormatProvider). Z tej metody jest documentation pierwszym parametrem jest:

Odniesienie wartości null (Nothing w języku Visual Basic) do korzystania z domyślnego formatu zdefiniowany dla rodzaju IFormattable realizacji.

A z dokumentacją DateTime.ToString(String, IFormatProvider) metody badaniem.

Jeśli format jest null lub pusty ciąg (""), standardowego formatu specyfikatorem, "G", jest wykorzystywana.

Oznacza to, że reprezentacja będzie kombinacją ShortDatePattern i LongTimePattern właściwości należących do listy CurrentCulture

Jeśli chcesz specjalnego formatu dla swojej klasy niestandardowego można override the .ToString() method swojego rodzaju zmienić swoje zachowanie .

7

W przeciwieństwie do tego, co niektórzy myślą, DateTime.ToString()nie będzie wywoływany jako. W .NET obiekt może mieć dwa sposoby "samodoskonalenia": przesłaniając metodę string Object.ToString() i implementując interfejs IFormattable. DateTime wykonuje oba.

... Teraz podczas próby robi

Console.WriteLine(DateTime.Now); 

pustkę public static void WriteLine(Object value) przeciążenie wybrano (widać go, jeśli Ctrl + kliknięcie na WriteLine w Visual Studio). Metoda ta po prostu wywołuje metodę TextWriter.WriteLine(value), który robi:

IFormattable f = value as IFormattable; 
if (f != null) 
    WriteLine(f.ToString(null, FormatProvider)); 
else 
    WriteLine(value.ToString()); 

Wszystko to można łatwo zauważyć stosując ILSpy i szuka Console.WriteLine.