I was wondering if I already knew an object was a string if it was faster to cast it or to call ToString(). I thought it would be faster to call ToString() because casting has to do some type checking while the String class overrides ToString to return itself:
1 2 3 4 5 6 7 8 9 | public class String { //... public override string ToString() { return this ; } } |
By this reasoning, I figured that (a is string && a.ToString().Length < 4000) would be cheaper than (a is string && ((string)a).Length < 4000).
It turns out they are both six IL instructions:
Calling ToString
1 2 3 4 5 6 | L_0007: ldloc.0 L_0008: isinst string L_000d: brfalse.s L_0023 L_000f: ldloc.0 L_0010: callvirt instance string [mscorlib]System.Object::ToString() L_0015: callvirt instance int32 [mscorlib]System.String::get_Length() |
Casting
1 2 3 4 5 6 | L_0025: ldloc.0 L_0026: isinst string L_002b: brfalse.s L_0041 L_002d: ldloc.0 L_002e: castclass string L_0033: callvirt instance int32 [mscorlib]System.String::get_Length() |
So… now what is the cost difference between the castclass operator and the virtual method call to the ToString method?
Turns out the cast takes about 75% of the time of a ToString call.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using System; static class Program { static void Main() { object o = "a string "; string a; string b; Boolean r = (o is string && o.ToString().Length < 4000); r = (o is string && (( string )o).Length < 4000); DateTime t = DateTime.Now; for ( int i = int .MinValue; i < int .MaxValue; i++) a = ( string )o; Console.WriteLine(DateTime.Now - t); t = DateTime.Now; for ( int i = int .MinValue; i < int .MaxValue; i++) b = o.ToString(); Console.WriteLine(DateTime.Now - t); } } |