The system that I am currently working on depends a lot on casting an object to an interface to see if it implements that interface. If it does, the system will take one action, if not, it will take a different action. Because of this, casting performance is very important to the overall performance of the software.
As far as I am aware, there are 4 ways in C# to test if a given instance of an object implements an interface (without knowing the exact type of the instance).
1. “as” cast after an “is” check:
if (castingObject is StringBuilder)
{
StringBuilder testBuilder = castingObject as StringBuilder;
// do stuff
}
else
{
// do other stuff
}
2. “as” cast with a null check:
StringBuilder testBuilder = castingObject as StringBuilder;
if (null != testBuilder)
{
// Do stuff
}
else
{
// Do other stuff
}
3. Explicit cast after an “is” check:
if (castingObject is StringBuilder)
{
StringBuilder testBuilder = (StringBuilder)castingObject;
// Do Stuff
}
else
{
// Do Other Stuff
}
4. Explicit cast with InvalidCastException:
try
{
StringBuilder testBuilder = (StringBuilder)castingObject;
// Do Stuff
}
catch(InvalidCastException)
{
// Do other stuff.
}
Method #4 should clearly be the worst performing option if you expect any number of the casts to fail (since throwing an exception is very expensive in .NET). So which of the three remaining methods would result in the best performance? Well, the only way to know for sure is to measure it, so that’s what I did.
As Cast with Is check: 0.0082533 seconds.
As Cast with Null check: 0.0077226 seconds.
Explicit Cast with Is check: 0.008119 seconds.
Explicit Cast with No check: 448.7026034 seconds.
Judging from these results, doing an “as” cast followed by a null check is the fastest way to test if an object instance is of a certain type. Of course, there is not enough of a difference between any of the first three methods to make me redo any existing code, and I certainly wouldn’t sacrifice readability/maintainability just to grab 5 milliseconds or so over 200,000 casts.
If you are curious I ran the casts inside a 100,000 iteration loop, with one “successful” cast and one “failed” cast, for a 50% success rate. A more clever test would take into account the actual expected failure rate of the casts and use that to measure the performance, but this was just a question of curiosity for me – as I mentioned the possible improvements are too small for me to worry about as long as I avoid the explicit cast with no checks.