2012-12-11 14 views
31

Würde jemand erklären wollen, wie dieser Code die folgende Ausgabe erzeugt?Überschreibende und optionale Parameter

using System; 

namespace ConsoleApplication1 
{ 
    class Test 
    { 
     public override string ToString() { return "ToString override"; } 
     public string ToString(string optional = "") 
      { return String.Format("ToString with optional parameter {0}", optional); } 
    } 

    class Test2 
    { 
     public new string ToString() { return "ToString new"; } 
     public string ToString(string optional = "") 
      { return String.Format("ToString with optional parameter {0}", optional); } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Test one = new Test(); 
      Test2 two = new Test2(); 
      Console.WriteLine(one); 
      Console.WriteLine(one.ToString()); 
      Console.WriteLine(one.ToString("foo")); 
      Console.WriteLine("--"); 
      Console.WriteLine(two); 
      Console.WriteLine(two.ToString()); 
      Console.WriteLine(two.ToString("bar")); 
      Console.ReadKey(); 
     } 
    } 
} 

ToString überschreibt

ToString mit optionalen Parametern

ToString mit optionalem Parameter foo

-

ConsoleApplication1.Test2

ToString neu

ToString mit optionalem Parameter bar

+3

Welche Zeile verstehst du nicht? (Es wäre langwierig, über sie alle ins Detail zu gehen.) –

+0

Grundsätzlich, wie der Compiler zwischen den verschiedenen Methoden wählt, da sie identische Signaturen haben. – pneuma08

+1

Sie haben keine identischen Signaturen ... und wieder würde es helfen, wenn Sie sagen würden * welche * Zeilen Sie feststecken. Wie viel hast du versucht zu verstehen, wie die Überladungsauflösung funktioniert? Übrigens gibt es so etwas wie C# 4.5 nicht. –

Antwort

49

Okay, da es von allgemeinem Interesse ist, ist hier eine kurze Version:

Console.WriteLine (eins)

Das die WriteLine(object) verwenden Überlast, die wiederum die object.ToString() virtuelle Methode ausführt, überschrieben in One - daher die Ausgabe von ToString override

Console.WriteLine (one.ToString())

Das bei One schauen und sehen, welche Methoden neu deklarierten Methoden - Diskontierung Überschreibungen. Es gibt genau eine solche Methode, die anwendbar ist - diejenige mit dem optionalen Parameter. Dies wird ausgeführt, wobei der Standardwert verwendet wird, der zur Ausgabe von ToString with optional parameter führt.

Console.WriteLine (one.ToString ("foo"))

Gleiche wieder, aber dieses Mal der Compiler muss nicht den Standardwert verwenden, damit ToString with optional parameter foo

Console. WriteLine (zwei)

Auch dies wird die virtuelle object.ToString() Methode von WriteLine(object) aufrufen. Die Methode wurde nicht überschrieben. Daher wird die Standardimplementierung verwendet, die den Namen des Typs zurückgibt. Dies führt zur Ausgabe von ConsoleApplication1.Test2.

Console.WriteLine (two.ToString())

Der Compiler schaut auf die alle Verfahren in Two erklärt, welche nicht zwingenden virtuellen Methoden. In diesem Fall gibt es zwei solche Methoden - die parameterlose und die mit dem optionalen Parameter. Das parameterlose ist enthalten, da es neu ist statt eine Basisklassenmethode überschreiben.

Die parameterlose Methode wird als "besserer" Kandidat angesehen, da der Compiler es vorzieht, eine Methode aufzurufen, die keine optionalen Parameter ausfüllt.Daher ist der Ausgang ToString new

Console.WriteLine (two.ToString ("bar"))

Wieder der Compiler bei allen Verfahren in Two erklärt sieht die nicht überwiegende virtuelle Methoden. In diesem Fall gibt es zwei solche Methoden - aber die parameterlose Methode ist nicht anwendbar, so dass nur die eine mit dem optionalen Parameter übrig bleibt. Der Compiler muss nicht Verwendung der Standardwert des optionalen Parameters hier, wie es trotzdem ein Argument bekommt ist ... so ist der Ausgang ToString with optional parameter bar

Für viel mehr dazu, die Sprache C# Spezifikation lesen - oder für ein halbwegs Haus, siehe meine article on overloading.

+3

Mühsam, aber informativ, danke für das Schreiben sie –

+0

Gute Sachen Jon (wie immer). Ich kam langsam dazu, alles auszuarbeiten. Die Hauptüberraschungspunkte sind, dass es 'object.ToString()' und nicht die 'ToString' auf dem Objekt verwendet und die Tatsache, dass es neu definierte Methoden den vererbten Methoden vorzieht. – Chris

+71

Good Guy Jon Skeet: sagt: "Es wäre mühsam, über sie alle ins Detail zu gehen", geht ausführlich auf alle ein. – Rawling