I have a situation where I need to downcast twice in one procedure using :?>
. I have a custom EventArgs
class (which inherits System.EventArgs
), and an instance of an abstract class within that custom EventArgs
. Upon receiving the event, I need to downcast twice. Once for the custom EventArgs
, and once for the abstract class within that custom EventArgs
. I have to do this potentially millions of times a day, so I'm wondering if there's anything inherently slow about downcasting.

- 6,591
- 33
- 50

- 6,066
- 13
- 54
- 95
-
4Have you benchmarked it? I certainly wouldn't *expect* it to be slow - 10 million times per day is only 115 times per second on average, which is a *really* small number for something like casting. – Jon Skeet Jul 13 '15 at 18:50
-
3You're asking a highly subjective question. Slow is relative, so unless you can give a concrete comparison point its quite difficult to answer your question. – N_A Jul 13 '15 at 19:22
-
So for instance, exception handling is slow, and programmers are generally discouraged from using exceptions to handle main workflow. I was wondering whether downcasting had a similar issue. – user3685285 Jul 14 '15 at 13:41
1 Answers
For grins, I put together the following little function:
let castToStream (o:Object) = o :?> Stream
and called it with the following code:
[<EntryPoint>]
let main argv =
let stm1 = new FileStream("output.tmp", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)
let obj = stm1 :> Object
let stm2 = castToStream obj
0 // return an integer exit code
When it is compiled, castToStream
turns into this IL:
.method public static class [mscorlib]System.IO.Stream
castToStream(object o) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: unbox.any [mscorlib]System.IO.Stream
IL_0007: ret
} // end of method Program::castToStream
which in this case is effectively 1 real instruction, unbox.any. Unbox.any for a reference type is equivalent to a castclass instruction. From the description, you'll take a one-time initial hit to load the type if it's not already loaded, then it's going to be a whatever magic is necessary to determine if the types are equivalent (likely using Type.IsAssignableFrom(), but I don't know for sure). However, unless your class hierarchy is super deep (and it shouldn't be), I would expect this to take microseconds on a typical machine.
For the curious, I initially had the code for castToStream inline, but the f# compiler saw through my shenanigans and removed all the casting entirely.

- 48,267
- 11
- 78
- 120