2015-07-31 12 views
8

Jaki jest cel używania String.Concat(Object) zamiast String.Concat(String) w C#? Dlaczego po prostu nie użyć niejawnego wywołania zamiast podania samego Object.ToString(), które może również spowodować boks?Cel String.Concat (Object) zamiast String.Concat (String)

Int32 i = 5; 
String s = "i = "; 

// Boxing happens, ToString() is called inside 
Console.WriteLine(s + i); 
// Why compiler doesn't call ToString() implicitly? 
Console.WriteLine(s + i.ToString()); 

Daje nam następujące IL.

.method private hidebysig static void MyDemo() cil managed 
{ 
    // Code size  47 (0x2f) 
    .maxstack 2 
    .locals init ([0] int32 i, [1] string s) 
    IL_0000: nop 
    IL_0001: ldc.i4.5 
    IL_0002: stloc.0 
    IL_0003: ldstr  "i = " 
    IL_0008: stloc.1 
    IL_0009: ldloc.1 
    IL_000a: ldloc.0 
    IL_000b: box  [mscorlib]System.Int32 
    IL_0010: call  string [mscorlib]System.String::Concat(object, object) 
    IL_0015: call  void [mscorlib]System.Console::WriteLine(string) 
    IL_001a: nop 
    IL_001b: ldloc.1 
    IL_001c: ldloca.s i 
    IL_001e: call  instance string [mscorlib]System.Int32::ToString() 
    IL_0023: call  string [mscorlib]System.String::Concat(string, string) 
    IL_0028: call  void [mscorlib]System.Console::WriteLine(string) 
    IL_002d: nop 
    IL_002e: ret 
} // end of method Program::MyDemo 
+0

Dobre pytanie. Dodałbym tutaj: dlaczego nie ma metody 'string Concat (string s, T value)', która będzie używana przez operatora '+'. – Dennis

+0

@Dennis, jaki byłby tego pożytek? –

+0

@Dennis W jaki sposób kompilator konkatenuje 'T value' z' string s'? Czy jakiekolwiek 'T' może być w ogóle łączone? –

Odpowiedz

3

Dlaczego powinien to robić kompilator? Nie może.

Jeśli przekazujesz obiekt (w tym przypadku pudełkowy int), jedyną możliwością dla kompilatora jest wywołanie string.Concat(object, object). Nie można wywołać string.Concat(string, string), ponieważ oba parametry nie są zgodne z string i dlatego są zgodne z drugim przeciążeniem.

Zamiast tego zadzwoni pod numer string.Concat(object, object) i jeśli będzie to konieczne, będzie zawierał kod ToString.

Jako programista masz dokładną wiedzę na temat sposobu działania metody string.Concat. Kompilator nie wie, że ostatecznie wszystko to staje się string.

Co się stanie, jeśli jeden z jest null? ToString zakończy się niepowodzeniem z wyjątkiem. To nie ma sensu. Po prostu przepuść numer object i pozwól, aby kod sobie z nim poradził.

+1

Kompilator wie, że wszystkie typy dziedziczą obiekt ostatecznie. Obiekt zawiera metodę ToString(). Tak więc, gdy kompilator nie spełnia argumentu String funkcji oczekującej String, może niejawnie wywołać ToString(). –

+1

Ale ty jako programista masz intymną wiedzę na temat działania metody 'string.Concat'. Kompilator nie wie, że ostatecznie wszystko staje się "ciągiem". –

+2

@JohnDoe - gdzie jest linia podziału? Czy mówisz o tym, że * każdy * zestaw przeciążeń, gdzie istnieją dwa przeciążenia, gdzie akceptuje parametr 'string' w tej samej pozycji, w której drugi akceptuje parametr' object', powinien zawsze wywoływać 'ToString()' na obiekt, a zatem przeciążenie 'object' nie jest nigdy wywoływalne? –

0

referencyjny Źródło: http://referencesource.microsoft.com/#mscorlib/system/string.cs,8281103e6f23cb5c

ujawnia, że:

public static String Concat(Object arg0) { 
     Contract.Ensures(Contract.Result<String>() != null); 
     Contract.EndContractBlock(); 

     if (arg0 == null) 
     { 
      return String.Empty; 
     } 
     return arg0.ToString(); 
    } 

To po prostu tworzy reprezentację ciąg tego obiektu. Tak więc każdy przechodzący obiekt jest przekształcany w String. String.Empty, jeśli jest pusty. Myślę, że to również oszczędza nam przed sprawdzeniem obiektu "zerowego" przed przekształceniem go na string.

+1

Całkiem interesujące, że istnieje metoda konkatowania _ jednej rzeczy_. – IllidanS4

Powiązane problemy