Yushatak Yushatak - 3 months ago 21
C# Question

StringBuilder Extension Append Call Resolution

I've got an extension method that appends each object in an IEnumerable to a StringBuilder. It operates on IEnumerable with the type argument, though, so my question is will it trigger the Append() calls unique to separate types or will everything pass through as "object" and be inefficient? If I need to, I'll expand the function for special cases where StringBuilder has Append() calls unique to the type, but I need to know if I have to do it or not.

/// <summary>
/// Appends each object in the enumerable to the StringBuilder's content.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sb"></param>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="System.ArgumentOutOfRangeException"/>
public static StringBuilder AppendEach<T>(this StringBuilder sb, IEnumerable<T> e)
{
e.Do<T>(t => sb.Append(t));
return sb;
}

/// <summary>
/// Allows you to run code on each value in a collection in-line.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <param name="action"></param>
public static void Do<T>(this IEnumerable<T> e, Action<T> action)
{
foreach (T t in e) action(t);
}


Wasn't sure if the Do extension I was using would change the outcome of the question, so I included it instead of simplifying the code. I know some people would hang me for writing "LINQ methods with side effects" here, but that's not relevant to the question at hand.

Answer

No, it will call Append(Object) if you meant that by "will it trigger the Append() calls unique to separate types".

Since there happens to be a dispute. C# compiler must decide which method to use at compile time. It means that the chosen methods parameters must not conflict with variables you put in Append(...). Since the compiler does not know what T is at compile time it will choose Append(object) because it is the only one that will work whatever T is gonna be.

I've imitated the scenario:

public class C
{
public static void Show(object value)
{
    "object".Dump();
}

public static void Show(int value)
{
    "int".Dump();
}

public static void Show(string value)
{
    "string".Dump();
}
}

public class MyClass<T>
{
   public void Append(T value)
   {
C.Show(value);
   }
}

public void Main()
{
var c1 = new MyClass<int>();
var c2 = new MyClass<string>();
var c3 = new MyClass<object>();

c1.Append(1);
c2.Append("1");
c3.Append(2);
}

It shows "object" 3 times.

BTW. If you remove the object-method from the class it will not compile for it won't be able to find a suitable method.