2012-11-07 23 views
55

Warum verhalten sich die beiden string.Format-Aufrufe im folgenden Code nicht auf die gleiche Weise? In der ersten wird keine Ausnahme geworfen, aber in der zweiten wird eine ArgumentNullException geworfen.Wie string.Format Nullwerte behandelt?

static void Main(string[] args) 
{ 
    Exception e = null; 
    string msgOne = string.Format("An exception occurred: {0}", e); 
    string msgTwo = string.Format("Another exception occurred: {0}", null); 
} 

Könnte mir bitte jemand helfen, den Unterschied zwischen den beiden zu verstehen?

+7

Die Chancen stehen Sie schlagen den [ 'params' override] (http://msdn.microsoft.com/en-us/library/b1csw23d.aspx) im zweiten Beispiel und' String.Format' testet, dass das Array gefüllt ist, bevor es mit der Iteration über die Sammlung fortfährt und Werte einfügt. –

+0

@BradChristie Sie sollten das als Antwort schreiben. – erikkallen

Antwort

43

Ich rate hier, aber es scheint der Unterschied zu sein, welcher überladener Anruf Sie schlagen. String.Format hat mehrere Überladungen, es ist nur was Sie treffen.

Im ersten Beispiel wäre es sinnvoll, dass Sie String.Format(string,object) treffen.

Im zweiten Beispiel durch null Bereitstellung sind Sie höchstwahrscheinlich String.Format(string,params object[]) schlagen, die, gemäß der Dokumentation, ein ArgumentNullException erhöhen würde, wenn:

Format oder args null ist.

Wenn Sie .NET4 laufen lassen, versuchen benannte Parameter verwendet:

String.Format("Another exception occured: {0}", arg0: null); 

Warum es trifft den params object[] Überlastung? Wahrscheinlich, weil null kein Objekt ist, und die Art und Weise params funktioniert ist, dass Sie entweder jeden Wert als ein neues Objekt in den Aufruf übergeben können oder übergeben Sie es ein Array der Werte. Das heißt, die folgende sind one in the same:

String.Format("Hello, {0}! Today is {1}.", "World", "Sunny"); 
String.Format("Hello, {0}! Today is {1}.", new Object[]{ "World", "Sunny" }) 

So ist es das Ihre Aussage Aufruf etwas entlang der Linien der Übersetzung:

String format = "Another exception occured: {0}"; 
Object[] args = null; 
String.Format(format, args); // throw new ArgumentNullException(); 
+0

Außerdem: Versuchen Sie den Unterschied zwischen 'string.Format (" Vorkommen: {0} ", (object []) null)' und 'string.Format (" Vorkommen: {0} ", (Objekt) null)'. Es gibt noch eine weitere Möglichkeit: 'string.Format (" Okzidiert: {0} ", neu [] {(Objekt) null,})'. Problem passiert nur im ersten Fall, denke ich. –

8

In Ihrem ersten Beispiel, Sie Format(String, Object) schlagen, die aussieht so, wenn zerlegt:

public static string Format(string format, object arg0) 
{ 
    return Format(null, format, new object[] { arg0 }); 
} 

Notiere die new object[] um die.

Die zweite, Sie sind offensichtlich treffen die Format(string, object[]) Verwendung, mindestens das ist derjenige aufgerufen wird, wenn ich den gleichen Test durchführen. Zerlegt, sieht das wie folgt aus:

public static string Format(string format, params object[] args) 
{ 
    return Format(null, format, args); 
} 

So davon alle tatsächlich zu Format(IFormatProvider, string, object[]) bekommen geschleust. Cool, schauen wir uns die ersten Zeilen dort an:

public static string Format(IFormatProvider provider, string format, params object[] args) 
{ 
    if ((format == null) || (args == null)) 
    { 
     throw new ArgumentNullException((format == null) ? "format" : "args"); 
    } 
... 
} 

... welp, da ist dein Problem, genau da! Der erste Aufruf ist das Umbrechen in ein neues Array, also ist es nicht null. Wenn Sie NULL explizit übergeben, wird dies aufgrund der spezifischen Instanz von Format(), die aufruft, nicht ausgeführt.

2

Der erste Aufruf wird als Aufruf von Format (Objekt) aufgelöst, während der zweite Aufruf als Aufruf von Format (Objekt []) aufgelöst wird. Nullparameter werden durch diese verschiedenen Überladungen unterschiedlich behandelt.

Die Überladungsauflösung ist here beschrieben. Der relevante Teil ist, dass für den zweiten Aufruf von Format eine Überladung von Format (params object []) auf Format (object []) erweitert wird, welches Format (object) vorgezogen wird. Das Literal-Null ist sowohl ein Objekt [] und ein Objekt, aber Objekt [] ist spezifischer, so dass gewählt wird.

-3

Es gibt zwei Unterschiede, die folgen:

  1. Hier wird Nullwert zugewiesen.

    Exception e = null; 
    string msgOne = string.Format("An exception occurred: {0}", e); 
    
  2. Hier kann Nullwert nicht im String-Format gelesen werden, die Fehler Gießen bedeutet ein.

    string msgTwo = string.Format("Another exception occurred: {0}", null); 
    

Ich gebe Ihnen einfaches Beispiel: Hier können Sie den NULL-Wert als String-Format nicht lesen.

string str = null.toString();