Purpose of String.Concat(Object) instead of String.Concat(String)
Asked Answered
A

2

8

What is the purpose of using String.Concat(Object) instead of String.Concat(String) in C#? Why just not use an implicit call of Object.ToString() instead of passing an object itself that may also cause boxing to happen?

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());

Gives us the following 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
Altimetry answered 31/7, 2015 at 7:45 Comment(4)
Good question. I'd add here: why there's no string Concat<T>(string s, T value) method, which will be used by + operator.Penicillin
@Penicillin what would be the use of that?Lancelancelet
@Penicillin How would the compiler concatenate T value with string s? Can any T be concatenated at all?Diverting
It will be enough to call return string.Concat(s, value.ToString()); inside. For value types this will avoid boxing.Penicillin
L
3

Why should the compiler do that? It can't.

If you pass in an object (in this case a boxed int), the only possibility for the compiler is to call string.Concat(object, object). It can't call string.Concat(string, string) since not both of the parameters are a string and thus complies to the second overload.

Instead, it calls string.Concat(object, object) and does a ToString inside if applicable.

You as a developer have intimate knowledge of how the string.Concat method works. The compiler doesn't know that eventually it all becomes a string.

Also, what would happen if one of the objects is null? The ToString will fail with an exception. This doesn't make sense. Just pass in the object and let the code handle it.

Lancelancelet answered 31/7, 2015 at 7:49 Comment(5)
Compiler does know that all the types inherit Object ultimately. Object contains ToString() method. Thus when compiler meets not a String argument of a function expecting String it may implicitly call ToString().Altimetry
But you as a developer have intimate knowledge of how the string.Concat method works. The compiler doesn't know that eventually it all becomes a string.Lancelancelet
@JohnDoe - where's the dividing line? Are you saying that, for any set of overloads where two overloads exist, where one accepts a string parameter in the same position that the other accepts an object parameter, it should always call ToString() on the object, and thus the object overload is never callable?Preside
Indeed. This may apply for this specific method (and some more), but 99% of the methods it doesn't apply.Lancelancelet
@Preside I'm just interested why Object overload ever exists since any Object can be ToString'ed. If an Object is uninitialized (NULL) there is probably a problem with code (using uninitialized variables), thus an Object overload 1) hides an error from a programmer emitting an empty string; 2) causes unneeded boxing degrading the performance and memory usage.Altimetry
B
0

Reference Source: http://referencesource.microsoft.com/#mscorlib/system/string.cs,8281103e6f23cb5c

Reveals that:

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

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

It just simply creates a string representation of that object. So any object that you pass is converted into String. String.Empty if it is null. I think this also saves us from checking the "null" object before converting it to string.

Broach answered 31/7, 2015 at 7:57 Comment(1)
Quite interesting that there is a method to concat a single thing.Hurling

© 2022 - 2024 — McMap. All rights reserved.